Skip to content

Commit

Permalink
Split data-ga4-section into two attributes so that sections can be se…
Browse files Browse the repository at this point in the history
…t on individual filter inputs

Previously, data-ga4-section was used to set indexes on filter parent elements, as well as give a label to the filter. However, there has been a request for the labels to be more granual. For example, instead of having one label Topics, have a label Topic and Sub-topic on the individual filters, rather than one label on their parent div. To achieve this, data-ga4-section is now used to set the label on each input. data-ga4-filter-parent now exists in order to identify where to calculate the indexes for each filter.
  • Loading branch information
AshGDS committed Sep 19, 2023
1 parent 20ac4e4 commit 96cca17
Show file tree
Hide file tree
Showing 10 changed files with 37 additions and 25 deletions.
15 changes: 8 additions & 7 deletions app/assets/javascripts/analytics-ga4/ga4-finder-tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@

GOVUK.analyticsGa4.Ga4FinderTracker = {

// Finds the parent div containing the filters. Loops through each child div that has data-ga4-section on it . Sets an index on each of these child divs.
// Finds the parent div containing the filters. Loops through each child div that has data-ga4-filter-parent on it . Sets an index on each of these child divs.
setFilterIndexes: function () {
var filterContainer = document.querySelector('[data-ga4-filter-container]')

if (!filterContainer) {
return
}

var filterSections = filterContainer.querySelectorAll('[data-ga4-section]')
var filterParents = filterContainer.querySelectorAll('[data-ga4-filter-parent]')

for (var i = 0; i < filterSections.length; i++) {
filterSections[i].setAttribute('data-ga4-index', JSON.stringify({ index_section: i + 1, index_section_count: filterSections.length }))
for (var i = 0; i < filterParents.length; i++) {
filterParents[i].setAttribute('data-ga4-index', JSON.stringify({ index_section: i + 1, index_section_count: filterParents.length }))
}

window.GOVUK.triggerEvent(window, 'ga4-filter-indexes-added')
Expand All @@ -28,6 +28,7 @@
// changeEventMetadata is a string referring to the type of form change and the element type that triggered it. For example 'update-filter checkbox'.
trackChangeEvent: function (eventTarget, changeEventMetadata) {
changeEventMetadata = changeEventMetadata.split(' ')
var filterParent = eventTarget.closest('[data-ga4-filter-parent]')
var section = eventTarget.closest('[data-ga4-section]')
var changeType = changeEventMetadata[0]
var elementType = changeEventMetadata[1]
Expand All @@ -45,7 +46,7 @@
var elementValue = elementInfo.elementValue
data.text = elementValue
var wasFilterRemoved = elementInfo.wasFilterRemoved
data = this.setSchemaBasedOnChangeType(data, elementValue, elementType, wasFilterRemoved, changeType, section)
data = this.setSchemaBasedOnChangeType(data, elementValue, elementType, wasFilterRemoved, changeType, section, filterParent)

var schemas = new window.GOVUK.analyticsGa4.Schemas()
var schema = schemas.mergeProperties(data, 'event_data')
Expand Down Expand Up @@ -107,7 +108,7 @@
},

// Takes the GTM schema, the event target value, the event target HTML type, whether the filter was removed, the type of filter change it was, and the parent section heading. Populates the GTM object based on these values.
setSchemaBasedOnChangeType: function (schema, elementValue, elementType, wasFilterRemoved, changeType, section) {
setSchemaBasedOnChangeType: function (schema, elementValue, elementType, wasFilterRemoved, changeType, section, filterParent) {
var PIIRemover = new window.GOVUK.analyticsGa4.PIIRemover()

switch (changeType) {
Expand All @@ -121,7 +122,7 @@
schema.text = elementType === 'text' ? undefined : elementValue
} else {
schema.action = elementType === 'text' ? 'search' : 'select'
schema.index = this.getSectionIndex(section)
schema.index = this.getSectionIndex(filterParent)
}
break

Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/modules/mobile-filters-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
}

MobileFiltersModal.prototype.addGa4Tracking = function () {
var indexSectionCount = document.querySelectorAll('[data-ga4-section]').length
var indexSectionCount = document.querySelectorAll('[data-ga4-filter-parent]').length

this.triggerElement.setAttribute('data-ga4-event', JSON.stringify({
event_name: 'select_content',
Expand Down
10 changes: 8 additions & 2 deletions app/views/components/_date_filter.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
value: from_value,
controls: aria_controls_id,
hint: "For example, 2005 or 21/11/2014",
error_message: date_errors_from
error_message: date_errors_from,
data: {
ga4_section: name + " after"
}
} %>
<%= render "govuk_publishing_components/components/input", {
Expand All @@ -31,7 +34,10 @@
value: to_value,
controls: aria_controls_id,
hint: "For example, 2005 or 21/11/2014",
error_message: date_errors_to
error_message: date_errors_to,
data: {
ga4_section: name + " before"
}
} %>
</div>
<% end %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/components/_expander.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
css_classes << (shared_helper.get_margin_bottom) unless margin_bottom == 0
%>
<% if title %>
<%= tag.div class: css_classes, data: { module: "expander", 'open-on-load': open_on_load, 'ga4-section': title } do %>
<%= tag.div class: css_classes, data: { module: "expander", 'open-on-load': open_on_load, 'ga4-filter-parent': '' } do %>
<h3 class="app-c-expander__heading">
<span class="app-c-expander__title js-toggle"><%= title %></span>
<svg version="1.1" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="app-c-expander__icon app-c-expander__icon--up" aria-hidden="true" focusable="false"><path d="m798.16 609.84l-256-256c-16.683-16.683-43.691-16.683-60.331 0l-256 256c-16.683 16.683-16.683 43.691 0 60.331s43.691 16.683 60.331 0l225.84-225.84 225.84 225.84c16.683 16.683 43.691 16.683 60.331 0s16.683-43.691 0-60.331z"/></svg>
Expand Down
5 changes: 2 additions & 3 deletions app/views/components/_option_select.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@
<% end %>
<% filter_element = CGI::escapeHTML(filter) %>
<% end %>

<div
class="app-c-option-select" data-module="option-select" data-ga4-change-category="update-filter checkbox" data-ga4-section="<%= title %>"
class="app-c-option-select" data-module="option-select" data-ga4-change-category="update-filter checkbox" data-ga4-filter-parent
<% if local_assigns.include?(:closed_on_load) && closed_on_load %>data-closed-on-load="true"<% end %>
<% if local_assigns.include?(:closed_on_load_mobile) && closed_on_load_mobile %>data-closed-on-load-mobile="true"<% end %>
<% if local_assigns.include?(:aria_controls_id) %>data-input-aria-controls="<%= aria_controls_id %>"<% end %>
Expand All @@ -45,7 +44,7 @@
<svg version="1.1" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="app-c-option-select__icon app-c-option-select__icon--down" aria-hidden="true" focusable="false"><path d="m225.84 414.16l256 256c16.683 16.683 43.691 16.683 60.331 0l256-256c16.683-16.683 16.683-43.691 0-60.331s-43.691-16.683-60.331 0l-225.84 225.84-225.84-225.84c-16.683-16.683-43.691-16.683-60.331 0s-16.683 43.691 0 60.331z"/></svg>
</h3>

<%= content_tag(:div, role: "group", aria: { labelledby: title_id }, class: classes, id: options_container_id, tabindex: "-1") do %>
<%= content_tag(:div, role: "group", aria: { labelledby: title_id }, class: classes, id: options_container_id, tabindex: "-1", data: { ga4_section: title }) do %>
<div class="app-c-option-select__container-inner js-auto-height-inner">
<% if show_filter %>
<span id="<%= checkboxes_count_id %>"
Expand Down
2 changes: 1 addition & 1 deletion app/views/finders/_radio_facet.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="facet-container" data-ga4-change-category="update-filter radio" data-ga4-section="">
<div class="facet-container" data-ga4-change-category="update-filter radio" data-ga4-section="" data-ga4-filter-parent>
<%= render "govuk_publishing_components/components/radio", {
name: radio_facet.key,
small: true,
Expand Down
8 changes: 5 additions & 3 deletions app/views/finders/_taxon_facet.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
<%= render "components/expander", {
title: "Topic"
} do %>
<div class="js-taxonomy-select" data-ga4-change-category="update-filter select">
<div class="js-taxonomy-select" data-ga4-change-category="update-filter select" data-ga4-section="Topic">

<%= render "govuk_publishing_components/components/select", {
id: 'level_one_taxon',
label: "Topic",
full_width: true,
options: taxon_facet.topics
options: taxon_facet.topics,
}
%>
<div class="js-required govuk-form-group gem-c-select">

<div class="js-required govuk-form-group gem-c-select" data-ga4-section="Sub-topic">
<%= render "govuk_publishing_components/components/select", {
id: 'level_two_taxon',
label: "Sub-topic",
Expand Down
2 changes: 1 addition & 1 deletion docs/analytics-ga4/ga4-filter-expand-collapse.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ The tracking relies on the `ga4-finder-tracker` running the `setFilterIndexes` f

Therefore, some code exists in `expander.js` and `option-select.js` to wait for a custom JavaScript event before setting any GA4 attributes. This event is called `ga4-filter-indexes-added`. The `setFilterIndexes` function fires the `ga4-filter-indexes-added` event when it has finished running. When this event has fired, `addFilterButtonTracking` in `ga4-finder-tracker` will then be called, and will set the relevant GA4 attributes on each filter's accordion heading.

The mobile "Filter" toggle button doesn't rely on `setFilterIndexes`, because it only uses an `index_total` in its tracking, which can be grabbed by running `document.querySelectorAll(['data-ga4-section']).length`. The filter accordion headings however need their specific index position within the filter list, which is why they wait for more specific indexes to be added to the DOM first.
The mobile "Filter" toggle button doesn't rely on `setFilterIndexes`, because it only uses an `index_total` in its tracking, which can be grabbed by running `document.querySelectorAll(['data-ga4-filter-parent']).length`. The filter accordion headings however need their specific index position within the filter list, which is why they wait for more specific indexes to be added to the DOM first.

The `addFilterButtonTracking` function in `ga4-finder-tracker`, which adds GA4 attributes to the filter accordion headings, will grab the `data-ga4-index` value from the trigger button's parent div when run. It will then merge the index attributes onto the existing GA4 object we have constructed for the buttons, and then append the completed GA4 object to the button.
6 changes: 3 additions & 3 deletions docs/analytics-ga4/ga4-finder-tracker.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ This script is used to add GA4 tracking to the GOVUK finders in `finder-frontend
```html
<form id="myForm">
<div data-ga4-filter-container>
<div data-ga4-section="Topics">
<select data-ga4-change-category="update-filter select">
<div data-ga4-filter-parent>
<select data-ga4-change-category="update-filter select" data-ga4-section="Topic">
<option value="1">Default option</option>
<option value="2">Option 1</option>
<option value="3">Option 2</option>
Expand Down Expand Up @@ -38,7 +38,7 @@ The flow of the tracker is:

a. Tag the parent `<div>` or wrapper element for your filters with `data-ga4-filter-container`. This tells our code where to look for filter sections, so that we can set an `index_section` for each filter.

b. Tag each filter's wrapper element with a `data-ga4-section` attribute. This key can also be populated with a string value, which will be used to populate the `section` value of our GTM object. For example, on a "Topics" filter `<div>` you could add `data-ga4-section="Topics"` or just `data-ga4-section`.
b. Tag each filter's wrapper element with a `data-ga4-filter-parent` attribute, so that indexes can be set. Tag each individual filter with `data-ga4-section="Topics"` to populate the GA4 section value for that filter.

c. Tag each element of the form that can trigger a `change` event with a `data-ga4-change-category`. This will contain some metadata about what the change is. The current categories are: `update-filter`, `update-sort`, `clear-all-filters` and `update-keyword`. As well as this, add the type of element that the filter is (further details on what types are tracked is documented below.) This assists with our tracker extracting the value of the filter. For example, a `<select>` element that updates a filter would have `data-ga4-change-category="update-filter select"`. A search box would have `data-ga4-change-category="update-keyword text"`.

Expand Down
10 changes: 7 additions & 3 deletions spec/javascripts/analytics-ga4/ga4-finder-tracker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ describe('GA4 finder change tracker', function () {
it('creates the correct GA4 object for adding/removing a checkbox filter', function () {
inputParent = document.createElement('div')
inputParent.setAttribute('data-ga4-change-category', 'update-filter checkbox')
inputParent.setAttribute('data-ga4-filter-parent', '')
inputParent.setAttribute('data-ga4-section', 'Your favourite chocolate')
var index = { index_section: 1, index_section_count: 1 }
inputParent.setAttribute('data-ga4-index', JSON.stringify(index))
Expand Down Expand Up @@ -135,6 +136,7 @@ describe('GA4 finder change tracker', function () {
it('creates the correct GA4 object for adding/removing a radio filter', function () {
inputParent = document.createElement('div')
inputParent.setAttribute('data-ga4-change-category', 'update-filter radio')
inputParent.setAttribute('data-ga4-filter-parent', '')
inputParent.setAttribute('data-ga4-section', 'Your favourite chocolate')
var index = { index_section: 1, index_section_count: 1 }
inputParent.setAttribute('data-ga4-index', JSON.stringify(index))
Expand Down Expand Up @@ -188,6 +190,7 @@ describe('GA4 finder change tracker', function () {
it('creates the correct GA4 object for adding/removing a <select> filter', function () {
inputParent = document.createElement('div')
inputParent.setAttribute('data-ga4-change-category', 'update-filter select')
inputParent.setAttribute('data-ga4-filter-parent', '')
inputParent.setAttribute('data-ga4-section', 'Your favourite chocolate')
var index = { index_section: 5, index_section_count: 15 }
inputParent.setAttribute('data-ga4-index', JSON.stringify(index))
Expand Down Expand Up @@ -235,6 +238,7 @@ describe('GA4 finder change tracker', function () {
it('creates the correct GA4 object for adding/removing a text filter', function () {
inputParent = document.createElement('div')
inputParent.setAttribute('data-ga4-change-category', 'update-filter text')
inputParent.setAttribute('data-ga4-filter-parent', '')
inputParent.setAttribute('data-ga4-section', 'Your favourite chocolate')
var index = { index_section: 2, index_section_count: 2 }
inputParent.setAttribute('data-ga4-index', JSON.stringify(index))
Expand Down Expand Up @@ -311,14 +315,14 @@ describe('GA4 finder change tracker', function () {

for (var i = 0; i < 5; i++) {
var div = document.createElement('div')
div.setAttribute('data-ga4-section', '')
div.setAttribute('data-ga4-filter-parent', '')
form.appendChild(div)
}

// Grabs each data-ga4-section element within a data-ga4-filter-container, and sets the appropriate indexes.
// Grabs each data-ga4-filter-parent element within a data-ga4-filter-container, and sets the appropriate indexes.
window.GOVUK.analyticsGa4.Ga4FinderTracker.setFilterIndexes()

var divs = form.querySelectorAll('[data-ga4-section]')
var divs = form.querySelectorAll('[data-ga4-filter-parent]')

for (i = 0; i < divs.length; i++) {
var expectedIndexObject = { index_section: i + 1, index_section_count: divs.length, index_link: undefined }
Expand Down

0 comments on commit 96cca17

Please sign in to comment.