2019-09-04 21:46:33 -07:00

117 lines
4.3 KiB
TypeScript

import { inject as service } from '@ember/service';
import RouterService from '@ember/routing/router-service';
import DwellTime from '@datahub/tracking/utils/dwell-time';
import { Time } from '@datahub/metadata-types/types/common/time';
import { action } from '@ember/object';
import { searchTrackingEvent } from '@datahub/tracking/constants/event-tracking/search';
import { DataModelName } from '@datahub/data-models/constants/entity';
import Service from '@ember/service';
import { isRouteEntityPageRoute } from '@datahub/data-models/utils/entity-route-name-resolver';
import { SuccessfulDwellTimeLength, searchRouteName } from '@datahub/tracking/constants/site-search-tracking';
import Transition from '@ember/routing/-private/transition';
import UnifiedTracking from '@datahub/tracking/services/unified-tracking';
/**
* Search service is used to maintain the same
* state on different parts of the app. Right now the only thing
* we need to persist is the keywords.
*/
export default class Search extends Service {
/**
* Keyword or query for the current search
*/
keyword: string;
/**
* Current entity of the search
*/
entity?: DataModelName;
/**
* Optional urn of the clicked search result
* @type {string}
*/
private clickedSearchResultUrn?: string;
/**
* On service instantiation a reference to a DwellTime instance is cached here to track dwell time
* @type {DwellTime}
* @memberof Search
*/
dwellTimeTracker: DwellTime;
/**
* References the application service to track user events, metrics and interaction
*/
@service('unified-tracking')
tracking: UnifiedTracking;
/**
* Router service used in tracking dwell time
*/
@service
router: RouterService;
/**
* Performs a set of operation when a search result is clicked
* @param {string} urn
* @returns {void}
* @memberof Search
*/
didClickSearchResult(urn: string): void {
// When a search result is clicked, initiate dwell time tracking
this.dwellTimeTracker.beginTracking();
// Also, track event as a click event
this.clickedSearchResultUrn = urn;
this.tracking.trackEvent({ ...searchTrackingEvent.SearchResultClick, name: this.clickedSearchResultUrn });
}
/**
* Sets the threshold value of the successful amount of dwell time on the component
* @instance
*/
successfulDwellTimeLength = SuccessfulDwellTimeLength;
/**
* Track SAT Click as an event
* This is inferred based on
* 1) Time spent or more specifically dwell time on viewing the entity page (see DwellTime class for differentiation)
* @link {DwellTime}
* 2) navigation sequence i.e. click from a search implied by dwell time, that lands on an entity page
* @param {number} dwellTime
* @returns boolean
*/
@action
trackSatClick(dwellTime: number, transition: Transition): boolean {
const isSATClick = this.isSATClick(dwellTime, transition);
if (isSATClick) {
this.tracking.trackEvent({ ...searchTrackingEvent.SearchResultSATClick, name: this.clickedSearchResultUrn });
}
return isSATClick;
}
init(): void {
super.init();
// Instantiate a DwellTime instance to track dwell time, which is essentially time spent on a search result page
this.dwellTimeTracker = new DwellTime(searchRouteName, this.router, this.trackSatClick);
}
/**
* Determines if the click can be judged as a satisfied click
* @param {Time} dwellTime the amount of time in milliseconds the user has dwelled on the page
* @param {Transition} { to, from } the current ember transition object containing the RouteInfo object being transitioned to or from
*/
isSATClick(dwellTime: Time, { to, from }: Transition): boolean {
const isReturningToSearch = Boolean(to && to.name === searchRouteName);
// If the user is returning to the search page, check if the dwellTime is meets or exceeds what is considered a successful amount of time
const isSufficientDwellTimeOnSearchReturn = isReturningToSearch && dwellTime >= this.successfulDwellTimeLength;
// If the dwell time is sufficient and the user is returning to search, or the user is navigating away from an entity route
// to a route that is not search this is considered a satisfied click
return isSufficientDwellTimeOnSearchReturn || (isRouteEntityPageRoute(from) && !isReturningToSearch);
}
}