diff --git a/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js b/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js index ce2910334a..1143485392 100644 --- a/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js +++ b/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js @@ -31,7 +31,9 @@ percent_scrolled: this.undefined, video_current_time: this.undefined, length: this.undefined, - video_percent: this.undefined + video_percent: this.undefined, + autocomplete_input: this.undefined, + autocomplete_suggestions: this.undefined } } } diff --git a/app/assets/javascripts/govuk_publishing_components/components/search-with-autocomplete.js b/app/assets/javascripts/govuk_publishing_components/components/search-with-autocomplete.js index 0de69690b6..e8f1e97593 100644 --- a/app/assets/javascripts/govuk_publishing_components/components/search-with-autocomplete.js +++ b/app/assets/javascripts/govuk_publishing_components/components/search-with-autocomplete.js @@ -15,6 +15,8 @@ window.GOVUK.Modules = window.GOVUK.Modules || {}; this.sourceUrl = this.$module.getAttribute('data-source-url') this.sourceKey = this.$module.getAttribute('data-source-key') + + this.suggestions = [] } init () { @@ -87,20 +89,25 @@ window.GOVUK.Modules = window.GOVUK.Modules || {}; url.searchParams.set('q', query) fetch(url, { headers: { Accept: 'application/json' } }) .then(response => response.json()) - .then((data) => { populateResults(data[this.sourceKey]) }) + .then((data) => { + this.suggestions = data[this.sourceKey] + populateResults(data[this.sourceKey]) + }) .catch(() => { populateResults([]) }) } // Callback used by accessible-autocomplete to submit the containing form when a suggestion is // confirmed by the user (e.g. by pressing Enter or clicking on it) submitContainingForm (value) { - if (this.$form) { - // The accessible-autocomplete component calls this callback _before_ it updates its - // internal state, so the value of the input field is not yet updated when this callback is - // called. We need to force the value to be updated before submitting the form, but the rest - // of the state can catch up later. - this.$autocompleteInput.value = value + // The accessible-autocomplete component calls this callback _before_ it updates its + // internal state, so the value of the input field is not yet updated when this callback is + // called. We need to force the value to be updated before submitting the form, but the rest + // of the state can catch up later. + this.$autocompleteInput.value = value + + this.submitGa4TrackingData() + if (this.$form) { if (this.$form.requestSubmit) { this.$form.requestSubmit() } else { @@ -110,6 +117,23 @@ window.GOVUK.Modules = window.GOVUK.Modules || {}; } } + submitGa4TrackingData () { + if (this.suggestions.length) { + const data = { + type: 'finder', + event_name: 'select_content', + tool_name: 'autocomplete', + autocomplete_input: this.$autocompleteInput.value, + autocomplete_suggestions: this.suggestions.join('|'), + length: this.suggestions.length + } + + const schemas = new window.GOVUK.analyticsGa4.Schemas() + const schema = schemas.mergeProperties(data, 'event_data') + window.GOVUK.analyticsGa4.core.sendData(schema) + } + } + // Sanitises a result coming back from the source to prevent XSS issues if the result happens to // contain HTML. sanitizeResult (value) { diff --git a/app/views/govuk_publishing_components/components/_search_with_autocomplete.html.erb b/app/views/govuk_publishing_components/components/_search_with_autocomplete.html.erb index 69323a8d24..0d5dc24209 100644 --- a/app/views/govuk_publishing_components/components/_search_with_autocomplete.html.erb +++ b/app/views/govuk_publishing_components/components/_search_with_autocomplete.html.erb @@ -21,7 +21,7 @@ %> <%= tag.div( class: classes.join(" "), - data: { module: "gem-search-with-autocomplete", source_url:, source_key: } + data: { module: "gem-search-with-autocomplete ga4-event-tracker", source_url:, source_key: } ) do %> <%= render "govuk_publishing_components/components/search", search_component_options %> <% end %> diff --git a/spec/javascripts/components/search-with-autocomplete-spec.js b/spec/javascripts/components/search-with-autocomplete-spec.js index 0de155b9a6..bbe862a93e 100644 --- a/spec/javascripts/components/search-with-autocomplete-spec.js +++ b/spec/javascripts/components/search-with-autocomplete-spec.js @@ -15,7 +15,7 @@ describe('Search with autocomplete component', () => {
@@ -215,4 +215,33 @@ describe('Search with autocomplete component', () => { expect(formData.get('q')).toEqual('updated value') expect(submitSpy).toHaveBeenCalled() }) + + it('submits correct Ga4 event data when a suggestion is confirmed', (done) => { + const $menu = fixture.querySelector('.gem-c-search-with-autocomplete__menu') + const $input = fixture.querySelector('input') + const $form = fixture.querySelector('form') + + const suggestions = ['foo', 'bar', 'baz'] + stubSuccessfulFetch(suggestions) + + $form.addEventListener('submit', (e) => { + e.preventDefault() + }) + + performInput($input, 'test query', () => { + $menu.querySelector('.gem-c-search-with-autocomplete__option').click() + + const ga4EventData = window.dataLayer[window.dataLayer.length - 1] + + expect(ga4EventData.event_data).toBeDefined() + expect(ga4EventData.event_data.type).toBe('finder') + expect(ga4EventData.event_data.event_name).toBe('select_content') + expect(ga4EventData.event_data.tool_name).toBe('autocomplete') + expect(ga4EventData.event_data.autocomplete_input).toBe($input.value) + expect(ga4EventData.event_data.autocomplete_suggestions).toBe(suggestions.join('|')) + expect(parseInt(ga4EventData.event_data.length, 10)).toBe(suggestions.length) + + done() + }) + }) }) diff --git a/spec/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.spec.js b/spec/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.spec.js index 5d368292e2..86a4e77059 100644 --- a/spec/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.spec.js +++ b/spec/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.spec.js @@ -41,7 +41,9 @@ describe('Google Analytics schemas', function () { percent_scrolled: undefined, video_current_time: undefined, length: undefined, - video_percent: undefined + video_percent: undefined, + autocomplete_input: this.undefined, + autocomplete_suggestions: this.undefined } } var returned = schemas.mergeProperties(data, 'example') @@ -76,7 +78,9 @@ describe('Google Analytics schemas', function () { percent_scrolled: undefined, video_current_time: undefined, length: undefined, - video_percent: undefined + video_percent: undefined, + autocomplete_input: this.undefined, + autocomplete_suggestions: this.undefined } } var returned = schemas.mergeProperties(data, 'example') @@ -111,7 +115,9 @@ describe('Google Analytics schemas', function () { percent_scrolled: undefined, video_current_time: undefined, length: undefined, - video_percent: undefined + video_percent: undefined, + autocomplete_input: this.undefined, + autocomplete_suggestions: this.undefined } } var returned = schemas.mergeProperties(data, 'example') @@ -147,7 +153,9 @@ describe('Google Analytics schemas', function () { percent_scrolled: undefined, video_current_time: undefined, length: undefined, - video_percent: undefined + video_percent: undefined, + autocomplete_input: this.undefined, + autocomplete_suggestions: this.undefined } } var returned = schemas.mergeProperties(data, 'example')