From 67878fb4177274722b181dbf072f04d56fdf5600 Mon Sep 17 00:00:00 2001 From: AshGDS <8880610+AshGDS@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:53:06 +0100 Subject: [PATCH] Split data-ga4-section into two attributes so that sections can be set 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. --- .../analytics-ga4/ga4-finder-tracker.js | 15 +++++------ .../modules/mobile-filters-modal.js | 2 +- app/views/components/_date_filter.html.erb | 10 ++++++-- app/views/components/_expander.html.erb | 2 +- app/views/components/_option_select.html.erb | 5 ++-- app/views/finders/_radio_facet.html.erb | 2 +- app/views/finders/_taxon_facet.html.erb | 6 +++-- .../ga4-filter-expand-collapse.md | 2 +- docs/analytics-ga4/ga4-finder-tracker.md | 6 ++--- .../analytics-ga4/ga4-finder-tracker.spec.js | 25 ++++++++++++++++--- .../modules/mobile-filters-modal.spec.js | 10 ++++---- 11 files changed, 56 insertions(+), 29 deletions(-) diff --git a/app/assets/javascripts/analytics-ga4/ga4-finder-tracker.js b/app/assets/javascripts/analytics-ga4/ga4-finder-tracker.js index 76a4932ee..f0f0b6c98 100644 --- a/app/assets/javascripts/analytics-ga4/ga4-finder-tracker.js +++ b/app/assets/javascripts/analytics-ga4/ga4-finder-tracker.js @@ -7,7 +7,7 @@ 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]') @@ -15,10 +15,10 @@ 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') @@ -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] @@ -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') @@ -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) { @@ -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 diff --git a/app/assets/javascripts/modules/mobile-filters-modal.js b/app/assets/javascripts/modules/mobile-filters-modal.js index a72513052..b93a6f7e1 100644 --- a/app/assets/javascripts/modules/mobile-filters-modal.js +++ b/app/assets/javascripts/modules/mobile-filters-modal.js @@ -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', diff --git a/app/views/components/_date_filter.html.erb b/app/views/components/_date_filter.html.erb index 2e4074dd5..3e8ac00e9 100644 --- a/app/views/components/_date_filter.html.erb +++ b/app/views/components/_date_filter.html.erb @@ -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", { @@ -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" + } } %> <% end %> diff --git a/app/views/components/_expander.html.erb b/app/views/components/_expander.html.erb index 509df4fe2..a41e40249 100644 --- a/app/views/components/_expander.html.erb +++ b/app/views/components/_expander.html.erb @@ -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 %>

<%= title %> diff --git a/app/views/components/_option_select.html.erb b/app/views/components/_option_select.html.erb index 144b3a9e3..14f3a180a 100644 --- a/app/views/components/_option_select.html.erb +++ b/app/views/components/_option_select.html.erb @@ -31,9 +31,8 @@ <% end %> <% filter_element = CGI::escapeHTML(filter) %> <% end %> -
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 %> @@ -45,7 +44,7 @@

- <%= 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 %>
<% if show_filter %> +
<%= render "govuk_publishing_components/components/radio", { name: radio_facet.key, small: true, diff --git a/app/views/finders/_taxon_facet.html.erb b/app/views/finders/_taxon_facet.html.erb index fcda45b06..aa4c33c2e 100644 --- a/app/views/finders/_taxon_facet.html.erb +++ b/app/views/finders/_taxon_facet.html.erb @@ -2,7 +2,8 @@ <%= render "components/expander", { title: "Topic" } do %> -
+
+ <%= render "govuk_publishing_components/components/select", { id: 'level_one_taxon', label: "Topic", @@ -10,7 +11,8 @@ options: taxon_facet.topics } %> -
+ +
<%= render "govuk_publishing_components/components/select", { id: 'level_two_taxon', label: "Sub-topic", diff --git a/docs/analytics-ga4/ga4-filter-expand-collapse.md b/docs/analytics-ga4/ga4-filter-expand-collapse.md index a49481f18..7ad4e7d05 100644 --- a/docs/analytics-ga4/ga4-filter-expand-collapse.md +++ b/docs/analytics-ga4/ga4-filter-expand-collapse.md @@ -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. \ No newline at end of file diff --git a/docs/analytics-ga4/ga4-finder-tracker.md b/docs/analytics-ga4/ga4-finder-tracker.md index 118b72660..45434c748 100644 --- a/docs/analytics-ga4/ga4-finder-tracker.md +++ b/docs/analytics-ga4/ga4-finder-tracker.md @@ -7,8 +7,8 @@ This script is used to add GA4 tracking to the GOVUK finders in `finder-frontend ```html
-
- @@ -38,7 +38,7 @@ The flow of the tracker is: a. Tag the parent `
` 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 `
` 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 ` 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)) @@ -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)) @@ -264,6 +268,21 @@ describe('GA4 finder change tracker', function () { expected.event_data.text = undefined expect(window.dataLayer[1]).toEqual(expected) + + // Ensure the section changes when data-ga4-section is set on individual inputs within the same data-ga4-filter-parent + var input2 = document.createElement('select') + input2.setAttribute('name', 'chocolates') + input2.setAttribute('data-ga4-section', 'Your second favourite chocolate') + input2.id = 'chocolates2' + input2.appendChild(option1) + input2.appendChild(option2) + inputParent.appendChild(input2) + window.GOVUK.triggerEvent(input2, 'change') + expected.event_data.event_name = 'select_content' + expected.event_data.section = 'Your second favourite chocolate' + expected.event_data.text = 'Belgian chocolate' + expected.event_data.action = 'select' + expected.event_data.index = { index_section: 5, index_section_count: 15, index_link: undefined } }) it('creates the correct GA4 object for clearing all filters', function () { @@ -311,14 +330,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 } diff --git a/spec/javascripts/modules/mobile-filters-modal.spec.js b/spec/javascripts/modules/mobile-filters-modal.spec.js index 77cc06fff..42da78329 100644 --- a/spec/javascripts/modules/mobile-filters-modal.spec.js +++ b/spec/javascripts/modules/mobile-filters-modal.spec.js @@ -16,16 +16,16 @@ describe('Mobile filters', function () { '

Filter

' + '
' + '
' + - '' + '' + '' + '' + - '' + + '' + '' + - '' + + '' + '' + - '' + - '' + + '' + + '' + '' +