Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add tracking to autocomplete suggestion selection #4280

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand Down Expand Up @@ -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 {
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 %>
31 changes: 30 additions & 1 deletion spec/javascripts/components/search-with-autocomplete-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Search with autocomplete component', () => {
<form id="search-form">
<div
class="gem-c-search-with-autocomplete"
data-module="gem-search-with-autocomplete"
data-module="gem-search-with-autocomplete ga4-event-tracker"
data-source-url="https://www.example.org/api/autocomplete.json?foo=bar"
data-source-key="suggestions"
>
Expand Down Expand Up @@ -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()
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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')
Expand Down
Loading