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

Spike: Refactor option-select component to isolate it from GA4 functionality specific to finder-frontend #3166

Closed
wants to merge 13 commits into from

Conversation

floehopper
Copy link
Contributor

Trello: https://trello.com/c/qs60lCxl

This is a spike into moving the GA4-related code out of the option-select component prior to extracting it into the govuk_publishing_components gem. My motivation was that I felt the GA4-related code was quite specific to finder-frontend.

Broadly the approach I've tried to take is to move the setting of all GA4-related data attributes out into the Rails facet templates rather than relying on setting them in a combination of in the component templates, in the component JavaScript, and in some more "global" GA4 JavaScript. This branch is very much a spike so I've made no attempt at fixing any linting or tests and while I've tried hard to make the commit notes as detailed and useful as possible, the last few are marked as "WIP" because either I'm not very happy with them or there is still some work to do in them.

I think my conclusion is that, while this specific approach might not be the best, it might be worth going for some kind of middle ground where it's possible to enable GA4-related functionality within the components, but supply non-generic values as data attributes from the facet templates. I've tried to explain this in a bit more detail in the final commit note.

I'm very happy to chat about any of this if it would be useful! Otherwise I'll probably close the PR fairly soon.

/cc @andysellick

This array of CSS classes is actually applied to the options container
within the component and not to the top-level element.

Also govuk_publishing_components components typically allow the CSS
classes on the top-level element to be customised via a `classes` local
variable, so I think the new name is less confusing.
I think it's simpler and more idiomatic to use the
GovukPublishingComponents::Presenters::ComponentWrapperHelper to build
the top-level element. Also it means the data attributes on the
top-level element can now easily be customised.

I'm planning to move the setting of the ga4-related data attributes out
of this template and this change will facilitate that.

For the moment I haven't used ComponentWrapperHelper#add_class to add
the "app-c-option-select" CSS class to the top-level element, because
the validation only allows the "gem-c-*" prefix; not the "app-c-*"
prefix. I plan to address this once the component is extracted into
GovukPublishingComponents which will then make it possible to customise
the CSS classes on the top-level element.
I want to extract the option-select component into the
govuk_publishing_components gem so that we can use it in the signon
application without duplicating the code.

The signon app doesn't yet fully support GA4 and we don't have any
immediate need to add GA tracking to our instances of option-select.
Even if we did, the tracking added here feels specific to
finder-frontend and so not suitable for extraction into the shared gem.

Setting the GA4-related data attributes outside the component decouples
the component from finder-frontend without losing any of the existing
GA4 tracking.

Also the e.g. the `ga4-change-category` data attribute is set in other
facet partials rather than in individual components, so this brings the
option-select facet into line with those.
I think it's simpler and more idiomatic to use the
GovukPublishingComponents::Presenters::ComponentWrapperHelper to build
the top-level element. Also it means the data attributes on the
top-level element can now easily be customised.

I'm planning to move the setting of the ga4-related data attributes out
of this template and this change will facilitate that.

For the moment I haven't used ComponentWrapperHelper#add_class to add
the "app-c-expander" CSS class to the top-level element, because the
validation only allows the "gem-c-*" prefix; not the "app-c-*" prefix. I
plan to address this once the component is extracted into
GovukPublishingComponents which will then make it possible to customise
the CSS classes on the top-level element.
I did something similar to the option-select component in a previous
commit. This brings the expander component into line with that change.

Setting the GA4-related data attributes outside the component decouples
the component from finder-frontend without losing any of the existing
GA4 tracking.
This means that more of the GA4-related data attributes for facets are
now set in the relevant facet partial template which I think makes the
code easier to follow.
This means that all the places where the "ga4-section" data attribute is
set are implemented using a Ruby Hash. I'm planning to set this value
based on the relevant facet object in a subsequent commit. This change
should make that easier.
This is effectively a more verbose version of the code it replaces. I
want to pass another local variable to each facet partial and this
change will make doing that easier.

The `option_select_facet_counter` local variable was previously being
provided automatically by Rails; now we're providing it explicitly.

Previously Rails was providing a `*_counter` local variable to each
facet partial where the prefix was based on the facet partial name. Now
we're providing the *same* local variable to each facet partial and,
although none of the other facet partials were using the counter, it
makes sense to give it a more generic name - hence I've named it
`index`.

There _might_ be a more elegant way to do this, but I couldn't find it!

The new version still relies on `FilterableFacet#to_partial_path`.

As an aside I found it a bit confusing that this index is 0-indexed
whereas the related index in the
GOVUK.analyticsGa4.Ga4FinderTracker.setFilterIndexes() JS function [1]
is 1-indexed. However, I haven't changed that here.

[1]: https://github.com/alphagov/finder-frontend/blob/665e954f26da3aa288f4e516b0272eb07c7ead55/app/assets/javascripts/analytics-ga4/ga4-finder-tracker.js#L10-L25
The facet_collection partial only ever uses the filterable facets, so we
can avoid some duplication by selecting the filterable facets in
FindersController#facets. However, there are a few callsites within the
controller which use the full list of facets, so I've introduced a new
`#all_facets` method to handle that without making it available as a
view helper method.
We're now able to provide the index from the facet partials thus
avoiding the need for the code in
GOVUK.analyticsGa4.Ga4FinderTracker.setFilterIndexes(). However, I've
left the code to trigger the "ga4-filter-indexes-added" event for now to
reduce the scope of this change. The plan is that the whole of
setFilterIndexes() will become redundant in a subsequent commit.

Note that the index is 0-indexed vs 1-indexed since the former is how
the Rails indexing was working. This means we currently have to add 1 in
the facet partials when setting the ga4-index.index_section value. It
might make more sense to change the index in FacetsIterator to be
1-indexed and change OptionSelectFacet#closed_by_default? to work with
this.

TODO: I'm not completely convinced that the Facet#has_ga4_section?
method belongs in the model.
This data attribute doesn't seem to depend on anything else so it's
simpler to move it into the relevant components at the cost of a small
amount of duplication. This is a small step towards making
addFilterButtonTracking() redundant.

Note that I may move the setting of this data attribute out into the
facet partials in a subsequent commit.
As opposed to in option-select.js or expander.js thereby avoiding the
need for GOVUK.analyticsGa4.Ga4FinderTracker.setFilterIndexes() to
trigger the "ga4-filter-indexes-added" custom event and the need to call
GOVUK.analyticsGa4.Ga4FinderTracker.addFilterButtonTracking() from
option-select.js & expander.js.

Now the ga4-related data attributes to be attached to the button created
dynamically by the components are supplied in the
`button_data_attributes` local variable in the relevant facet partial.
This is more awkward than I would've liked, because of the need to make
the button data attributes available at component JS initialization time
as opposed to just at component partial render time.

The awkwardness described above makes me think it would be worth
investigating some kind of middle ground where _some_ of the GA4
functionality is optionally enabled within the components but the
relevant distinguishing variables are still set in the facet partials,
i.e. it's probably OK for the components to "know" that they should set
`event_name` to "select_content" in the "ga4-event" data attribute, but
it's probably not OK for the components to "know" that they should set
`type` to "finder", so the latter should be passed in to the component
from the facet partial.

TODO:

* Make equivalent changes to the expander component and all the facet
  partials which directly or indirectly use it. This may be a bit more
  awkward!
* Consider making the index from FacetsIterator 1-indexed rather than
  0-indexed so we don't have to keep adding 1 in several places.
* Consier reducing duplication in the generation of the data attributes
  in the facet partials; perhaps by extracting a helper method.
* Completely remove setFilterIndexes() & addFilterButtonTracking()
* Do we still need to set the ga4-index data attribute on the component
  top-level element or was this only used by the component JS to obtain
  the ga4-index data? It would simplify the code in the facet partials if
  we only needed to pass the ga4-index data in the
  `button_data_attributes` and not in the `data_attributes` as well.
* Update docs/analytics-ga4/ga4-finder-tracker.md &
  docs/analytics-ga4/ga4-filter-expand-collapse.md docs to reflect the
  new approach.
@govuk-ci govuk-ci temporarily deployed to finder-frontend-pr-3166 September 21, 2023 11:14 Inactive
@andysellick andysellick mentioned this pull request Nov 29, 2023
@andysellick
Copy link
Contributor

Relevant improvements from this PR have been implemented in this PR: #3224 so closing this one.

@andysellick andysellick deleted the refactor-option-select-component branch May 21, 2024 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants