UNPKG

cruk-searchkit

Version:

Set of overriden and new searchkit components designed specifically for Cancer Research UK

143 lines (124 loc) 4.02 kB
import React from 'react'; import { SearchkitComponent } from "searchkit"; import gtmParts from 'react-google-tag-manager'; import { defaults } from 'lodash'; /** * Create our Google Tag Manager component. Follows the basic example found * here: * https://github.com/holidaycheck/react-google-tag-manager * * Adding a listener to the new results events is from: * http://docs.searchkit.co/stable/docs/core/SearchkitManager.html */ class CRUKSearchkitGTM extends SearchkitComponent { constructor(props) { super(props); this.previousState = {}; } /** * Tack on our script if needed. */ componentDidMount() { const dataLayerName = this.props.dataLayerName || 'dataLayer'; const scriptId = this.props.scriptId || 'react-google-tag-manager-gtm'; if (!window[dataLayerName]) { const gtmScriptNode = document.getElementById(scriptId); eval(gtmScriptNode.textContent); } /** * Setup our listener for new events. */ let resultsListener = this.searchkit.addResultsListener((results) => { this.trackResultsChange(results) }); } /** * Return the values of whether or not the search has been filtered, sorted, * searched geographically and also provide the chance to send on extra data. * * Also means you can override the "query" if your search isn't a fulltext * one. * * Should return an object with values, or an empty object. */ derivePayloadValues(results) { const searchState = this.searchkit.state; return {}; } /** * Track the result change sending data to GA/GTM. */ trackResultsChange(results) { /** * Construct the payload. */ const gtmSearchTitle = this.props.searchName || 'Unnamed React search'; const keywordField = this.props.keywordField || 'q'; const query = this.searchkit.state[keywordField]; let page = typeof this.searchkit.state.p == 'undefined' ? 1 : this.searchkit.state.p; let totalResults = this.getHitsCount(); /** * Figure out paging and filtering events. */ let previousPage = typeof this.previousState.p == 'undefined' ? 1 : this.previousState.p; let pagingEvent = page != previousPage && query == this.previousState.q; var pushObject = { 'event': 'site search event', 'content-name': '/search?query=' + query + '&cat=' + gtmSearchTitle + '&page=' + page, 'keyword': query, 'target': gtmSearchTitle, 'value': totalResults, 'searchFiltered': 'false', 'searchSorted': 'false', 'searchPaged': pagingEvent ? 'true' : 'false', 'searchNoResults': totalResults < 1 ? 'true' : 'false', 'searchGeo': 'false', 'pageNumber': page }; /** * Allow the object to be changed. */ const derivedValues = this.derivePayloadValues(results); let payload = defaults(derivedValues, pushObject); /** * Set the content-name to be constructed from other values. */ payload['content-name'] = '/search?query=' + payload.keyword + '&cat=' + payload.target + '&page=' + payload.pageNumber; /** * Push the event to dataLayer. */ dataLayer.push(payload); /** * Save state for later, this needs redux :C */ this.previousState = this.searchkit.state; } render() { const gtm = gtmParts({ id: this.props.gtmId, dataLayerName: this.props.dataLayerName || 'dataLayer', additionalEvents: this.props.additionalEvents || {} }); return ( <div> <div>{gtm.noScriptAsReact()}</div> <div id={this.props.scriptId || 'react-google-tag-manager-gtm'}> {gtm.scriptAsReact()} </div> </div> ); } } CRUKSearchkitGTM.propTypes = { gtmId: React.PropTypes.string.isRequired, dataLayerName: React.PropTypes.string, additionalEvents: React.PropTypes.object, scriptId: React.PropTypes.string, searchName: React.PropTypes.string, keywordField: React.PropTypes.string }; export default CRUKSearchkitGTM;