From c7084f14c11c8ef83d8846e343cc8207aa064fab Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 29 Jun 2023 11:49:59 +0200 Subject: [PATCH] MOBILE-4368 analytics: Log searches --- src/addons/mod/data/components/index/index.ts | 31 +++++++++++++++++++ .../mod/glossary/components/index/index.ts | 18 +++++++++++ src/core/features/courses/pages/list/list.ts | 23 +++++++++++++- .../features/tag/pages/search/search.html | 2 +- src/core/features/tag/pages/search/search.ts | 28 ++++++++++++++++- 5 files changed, 99 insertions(+), 3 deletions(-) diff --git a/src/addons/mod/data/components/index/index.ts b/src/addons/mod/data/components/index/index.ts index d412664f178..3b6c939d66c 100644 --- a/src/addons/mod/data/components/index/index.ts +++ b/src/addons/mod/data/components/index/index.ts @@ -45,6 +45,8 @@ import { AddonModDataModuleHandlerService } from '../../services/handlers/module import { AddonModDataPrefetchHandler } from '../../services/handlers/prefetch'; import { AddonModDataComponentsCompileModule } from '../components-compile.module'; import { AddonModDataSearchComponent } from '../search/search'; +import { CoreUrlUtils } from '@services/utils/url'; +import { CoreTime } from '@singletons/time'; const contentToken = ''; @@ -114,6 +116,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp protected entryChangedObserver?: CoreEventObserver; protected ratingOfflineObserver?: CoreEventObserver; protected ratingSyncObserver?: CoreEventObserver; + protected logSearch?: () => void; constructor( protected content?: IonContent, @@ -404,6 +407,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp // Add data to search object. if (modalData) { this.search = modalData; + this.logSearch = CoreTime.once(() => this.performLogSearch()); this.searchEntries(0); } } @@ -420,6 +424,8 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp try { await this.fetchEntriesData(); + + this.logSearch?.(); } catch (error) { CoreDomUtils.showErrorModalDefault(error, 'core.course.errorgetmodule', true); } finally { @@ -535,6 +541,31 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp this.analyticsLogEvent('mod_data_view_database'); } + /** + * Log search. + */ + protected async performLogSearch(): Promise { + if (!this.database || !this.search.searching) { + return; + } + + const params: Record = { + perpage: AddonModDataProvider.PER_PAGE, + search: !this.search.searchingAdvanced ? this.search.text : '', + sort: this.search.sortBy, + order: this.search.sortDirection, + advanced: this.search.searchingAdvanced ? 1 : 0, + filter: 1, + }; + + // @todo: Add advanced search parameters. Leave them empty if not using advanced search. + + this.analyticsLogEvent('mod_data_search_entries', { + data: params, + url: CoreUrlUtils.addParamsToUrl(`/mod/data/view.php?d=${this.database.id}`, params), + }); + } + /** * @inheritdoc */ diff --git a/src/addons/mod/glossary/components/index/index.ts b/src/addons/mod/glossary/components/index/index.ts index 053b507cfed..56f5c4b87c6 100644 --- a/src/addons/mod/glossary/components/index/index.ts +++ b/src/addons/mod/glossary/components/index/index.ts @@ -56,6 +56,7 @@ import { import { AddonModGlossaryModuleHandlerService } from '../../services/handlers/module'; import { AddonModGlossaryPrefetchHandler } from '../../services/handlers/prefetch'; import { AddonModGlossaryModePickerPopoverComponent } from '../mode-picker/mode-picker'; +import { CoreTime } from '@singletons/time'; /** * Component that displays a glossary entry page. @@ -86,6 +87,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity protected sourceUnsubscribe?: () => void; protected observers?: CoreEventObserver[]; protected checkCompletionAfterLog = false; // Use CoreListItemsManager log system instead. + protected logSearch?: () => void; getDivider?: (entry: AddonModGlossaryEntry) => string; showDivider: (entry: AddonModGlossaryEntry, previous?: AddonModGlossaryEntry) => boolean = () => false; @@ -226,6 +228,10 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity this.hasOfflineRatings = hasOfflineRatings; this.hasOffline = this.hasOfflineEntries || this.hasOfflineRatings; + + if (this.isSearch && this.logSearch) { + this.logSearch(); + } } /** @@ -424,11 +430,23 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity search(query: string): void { this.loadingMessage = Translate.instant('core.searching'); this.showLoading = true; + this.logSearch = CoreTime.once(() => this.performLogSearch(query)); this.entries?.getSource().search(query); this.loadContent(); } + /** + * Log search. + * + * @param query Text entered on the search box. + */ + protected async performLogSearch(query: string): Promise { + this.analyticsLogEvent('mod_glossary_get_entries_by_search', { + data: { mode: 'search', hook: query, fullsearch: 1 }, + }); + } + /** * @inheritdoc */ diff --git a/src/core/features/courses/pages/list/list.ts b/src/core/features/courses/pages/list/list.ts index 7e754f9ea8a..f61ba3d0a47 100644 --- a/src/core/features/courses/pages/list/list.ts +++ b/src/core/features/courses/pages/list/list.ts @@ -65,6 +65,7 @@ export class CoreCoursesListPage implements OnInit, OnDestroy { protected courseIds = ''; protected isDestroyed = false; protected logView: () => void; + protected logSearch?: () => void; constructor() { this.currentSiteId = CoreSites.getRequiredCurrentSite().getId(); @@ -159,7 +160,7 @@ export class CoreCoursesListPage implements OnInit, OnDestroy { try { if (this.searchMode) { if (this.searchText) { - await this.search(this.searchText); + await this.searchCourses(); } } else { await this.loadCourses(true); @@ -247,6 +248,7 @@ export class CoreCoursesListPage implements OnInit, OnDestroy { this.courses = []; this.searchPage = 0; this.searchTotal = 0; + this.logSearch = CoreTime.once(() => this.performLogSearch()); const modal = await CoreDomUtils.showModalLoading('core.searching', true); await this.searchCourses().finally(() => { @@ -268,6 +270,23 @@ export class CoreCoursesListPage implements OnInit, OnDestroy { this.fetchCourses(); } + /** + * Log search. + */ + protected async performLogSearch(): Promise { + if (!this.searchMode) { + return; + } + + CoreAnalytics.logEvent({ + type: CoreAnalyticsEventType.VIEW_ITEM_LIST, + ws: 'core_course_search_courses', + name: Translate.instant('core.courses.availablecourses'), + data: { search: this.searchText, category: 'course' }, + url: `/course/search.php?search=${this.searchText}`, + }); + } + /** * Load more courses. * @@ -305,6 +324,8 @@ export class CoreCoursesListPage implements OnInit, OnDestroy { this.searchPage++; this.canLoadMore = this.courses.length < this.searchTotal; + + this.logSearch?.(); } catch (error) { this.loadMoreError = true; // Set to prevent infinite calls with infinite-loading. !this.isDestroyed && CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorsearching', true); diff --git a/src/core/features/tag/pages/search/search.html b/src/core/features/tag/pages/search/search.html index 6126aa8c3c5..f428692cbd2 100644 --- a/src/core/features/tag/pages/search/search.html +++ b/src/core/features/tag/pages/search/search.html @@ -22,7 +22,7 @@

{{ 'core.tag.searchtags' | translate }}

autocorrect="off" [spellcheck]="false" [autoFocus]="false" [lengthCheck]="0" searchArea="CoreTag"> - + {{ 'core.tag.inalltagcoll' | translate }} diff --git a/src/core/features/tag/pages/search/search.ts b/src/core/features/tag/pages/search/search.ts index 5696f12d59f..a608bd19732 100644 --- a/src/core/features/tag/pages/search/search.ts +++ b/src/core/features/tag/pages/search/search.ts @@ -45,6 +45,7 @@ export class CoreTagSearchPage implements OnInit { searching = false; protected logView: () => void; + protected logSearch?: () => void; constructor() { this.logView = CoreTime.once(async () => { @@ -112,6 +113,8 @@ export class CoreTagSearchPage implements OnInit { */ async fetchTags(): Promise { this.cloud = await CoreTag.getTagCloud(this.collectionId, undefined, undefined, this.query); + + this.logSearch?.(); } /** @@ -140,11 +143,17 @@ export class CoreTagSearchPage implements OnInit { * Search tags. * * @param query Search query. + * @param collectionId Collection ID to use. * @returns Resolved when done. */ - searchTags(query: string): Promise { + searchTags(query: string, collectionId?: number): Promise { this.searching = true; this.query = query; + if (collectionId !== undefined) { + this.collectionId = collectionId; + } + + this.logSearch = CoreTime.once(() => this.performLogSearch()); CoreApp.closeKeyboard(); return this.fetchTags().catch((error) => { @@ -154,4 +163,21 @@ export class CoreTagSearchPage implements OnInit { }); } + /** + * Log search. + */ + protected async performLogSearch(): Promise { + if (!this.query) { + return; + } + + CoreAnalytics.logEvent({ + type: CoreAnalyticsEventType.VIEW_ITEM_LIST, + ws: 'core_tag_get_tag_cloud', + name: Translate.instant('core.tag.searchtags'), + data: { category: 'tag' }, + url: `/tag/search.php&query=${this.query}&tc=${this.collectionId}&go=${Translate.instant('core.search')}`, + }); + } + }