diff --git a/src/app/core/shared/search/search.service.spec.ts b/src/app/core/shared/search/search.service.spec.ts index 193a60315f..9399065ddf 100644 --- a/src/app/core/shared/search/search.service.spec.ts +++ b/src/app/core/shared/search/search.service.spec.ts @@ -25,6 +25,7 @@ import { PaginationService } from '../../pagination/pagination.service'; import { SearchConfigurationService } from './search-configuration.service'; import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; import { RequestEntry } from '../../data/request-entry.model'; +import { Angulartics2 } from 'angulartics2'; @Component({ template: '' }) class DummyComponent { @@ -57,6 +58,7 @@ describe('SearchService', () => { { provide: DSpaceObjectDataService, useValue: {} }, { provide: PaginationService, useValue: {} }, { provide: SearchConfigurationService, useValue: searchConfigService }, + { provide: Angulartics2, useValue: {} }, SearchService ], }); @@ -124,6 +126,7 @@ describe('SearchService', () => { { provide: DSpaceObjectDataService, useValue: {} }, { provide: PaginationService, useValue: paginationService }, { provide: SearchConfigurationService, useValue: searchConfigService }, + { provide: Angulartics2, useValue: {} }, SearchService ], }); diff --git a/src/app/core/shared/search/search.service.ts b/src/app/core/shared/search/search.service.ts index 7911db026d..f86c9c0379 100644 --- a/src/app/core/shared/search/search.service.ts +++ b/src/app/core/shared/search/search.service.ts @@ -33,6 +33,7 @@ import { SearchConfigurationService } from './search-configuration.service'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { RestRequest } from '../../data/rest-request.model'; import { BaseDataService } from '../../data/base/base-data.service'; +import { Angulartics2 } from 'angulartics2'; /** * A limited data service implementation for the 'discover' endpoint @@ -96,6 +97,7 @@ export class SearchService implements OnDestroy { private dspaceObjectService: DSpaceObjectDataService, private paginationService: PaginationService, private searchConfigurationService: SearchConfigurationService, + private angulartics2: Angulartics2, ) { this.searchDataService = new SearchDataService(); } @@ -320,6 +322,37 @@ export class SearchService implements OnDestroy { }); } + /** + * Send search event to rest api using angularitics + * @param config Paginated search options used + * @param searchQueryResponse The response objects of the performed search + */ + trackSearch(config: PaginatedSearchOptions, searchQueryResponse: SearchObjects) { + const filters: { filter: string, operator: string, value: string, label: string; }[] = []; + const appliedFilters = searchQueryResponse.appliedFilters || []; + for (let i = 0, filtersLength = appliedFilters.length; i < filtersLength; i++) { + const appliedFilter = appliedFilters[i]; + filters.push(appliedFilter); + } + this.angulartics2.eventTrack.next({ + action: 'search', + properties: { + searchOptions: config, + page: { + size: config.pagination.size, // same as searchQueryResponse.page.elementsPerPage + totalElements: searchQueryResponse.pageInfo.totalElements, + totalPages: searchQueryResponse.pageInfo.totalPages, + number: config.pagination.currentPage, // same as searchQueryResponse.page.currentPage + }, + sort: { + by: config.sort.field, + order: config.sort.direction + }, + filters: filters, + }, + }); + } + /** * @returns {string} The base path to the search page */ diff --git a/src/app/search-page/search-page.component.html b/src/app/search-page/search-page.component.html index 8424c0b531..73a952332f 100644 --- a/src/app/search-page/search-page.component.html +++ b/src/app/search-page/search-page.component.html @@ -1,2 +1 @@ - - + diff --git a/src/app/shared/search/search.component.ts b/src/app/shared/search/search.component.ts index f40947ad19..b5d328f42a 100644 --- a/src/app/shared/search/search.component.ts +++ b/src/app/shared/search/search.component.ts @@ -140,6 +140,11 @@ export class SearchComponent implements OnInit { */ @Input() showScopeSelector = true; + /** + * Whether or not to track search statistics by sending updates to the rest api + */ + @Input() trackStatistics = false; + /** * The current configuration used during the search */ @@ -360,8 +365,13 @@ export class SearchComponent implements OnInit { followLink('accessStatus', { isOptional: true, shouldEmbed: environment.item.showAccessStatuses }) ).pipe(getFirstCompletedRemoteData()) .subscribe((results: RemoteData>) => { - if (results.hasSucceeded && results.payload?.page?.length > 0) { - this.resultFound.emit(results.payload); + if (results.hasSucceeded) { + if (this.trackStatistics) { + this.service.trackSearch(searchOptions, results.payload); + } + if (results.payload?.page?.length > 0) { + this.resultFound.emit(results.payload); + } } this.resultsRD$.next(results); }); diff --git a/src/app/shared/search/themed-search.component.ts b/src/app/shared/search/themed-search.component.ts index f7d534399e..64a2befeb2 100644 --- a/src/app/shared/search/themed-search.component.ts +++ b/src/app/shared/search/themed-search.component.ts @@ -19,7 +19,7 @@ import { ListableObject } from '../object-collection/shared/listable-object.mode templateUrl: '../theme-support/themed.component.html', }) export class ThemedSearchComponent extends ThemedComponent { - protected inAndOutputNames: (keyof SearchComponent & keyof this)[] = ['configurationList', 'context', 'configuration', 'fixedFilterQuery', 'useCachedVersionIfAvailable', 'inPlaceSearch', 'linkType', 'paginationId', 'searchEnabled', 'sideBarWidth', 'searchFormPlaceholder', 'selectable', 'selectionConfig', 'showSidebar', 'showViewModes', 'useUniquePageId', 'viewModeList', 'showScopeSelector', 'resultFound', 'deselectObject', 'selectObject']; + protected inAndOutputNames: (keyof SearchComponent & keyof this)[] = ['configurationList', 'context', 'configuration', 'fixedFilterQuery', 'useCachedVersionIfAvailable', 'inPlaceSearch', 'linkType', 'paginationId', 'searchEnabled', 'sideBarWidth', 'searchFormPlaceholder', 'selectable', 'selectionConfig', 'showSidebar', 'showViewModes', 'useUniquePageId', 'viewModeList', 'showScopeSelector', 'resultFound', 'deselectObject', 'selectObject', 'trackStatistics']; @Input() configurationList: SearchConfigurationOption[] = []; @@ -57,6 +57,8 @@ export class ThemedSearchComponent extends ThemedComponent { @Input() showScopeSelector = true; + @Input() trackStatistics = false; + @Output() resultFound: EventEmitter> = new EventEmitter>(); @Output() deselectObject: EventEmitter = new EventEmitter();