govuk_publishing_components 32.0.0 → 33.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/component_guide/accessibility-test.js +0 -1
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +175 -0
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-ecommerce-tracker.js +1 -1
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-event-tracker.js +5 -13
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +80 -309
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js +2 -2
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +140 -0
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js +3 -0
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
- data/app/assets/javascripts/govuk_publishing_components/components/accordion.js +12 -1
- data/app/assets/javascripts/govuk_publishing_components/components/layout-super-navigation-header.js +13 -4
- data/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js +24 -8
- data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +83 -86
- data/app/assets/stylesheets/govuk_publishing_components/components/_big-number.scss +2 -5
- data/app/assets/stylesheets/govuk_publishing_components/components/_image-card.scss +1 -5
- data/app/assets/stylesheets/govuk_publishing_components/components/_input.scss +3 -5
- data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +10 -30
- data/app/assets/stylesheets/govuk_publishing_components/components/_search.scss +0 -7
- data/app/assets/stylesheets/govuk_publishing_components/components/_share-links.scss +0 -6
- data/app/views/govuk_publishing_components/components/_accordion.html.erb +14 -1
- data/app/views/govuk_publishing_components/components/_error_summary.html.erb +27 -26
- data/app/views/govuk_publishing_components/components/_layout_super_navigation_header.html.erb +2 -2
- data/app/views/govuk_publishing_components/components/_phase_banner.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/_share_links.html.erb +18 -15
- data/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/docs/accordion.yml +15 -3
- data/app/views/govuk_publishing_components/components/docs/button.yml +10 -0
- data/app/views/govuk_publishing_components/components/docs/share_links.yml +59 -30
- data/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml +10 -1
- data/app/views/govuk_publishing_components/components/feedback/_yes_no_banner.html.erb +3 -3
- data/config/locales/ar.yml +4 -1
- data/config/locales/az.yml +4 -1
- data/config/locales/be.yml +4 -1
- data/config/locales/bg.yml +4 -1
- data/config/locales/bn.yml +4 -1
- data/config/locales/cs.yml +4 -1
- data/config/locales/cy.yml +4 -1
- data/config/locales/da.yml +4 -1
- data/config/locales/de.yml +4 -1
- data/config/locales/dr.yml +4 -1
- data/config/locales/el.yml +4 -1
- data/config/locales/en.yml +20 -17
- data/config/locales/es-419.yml +4 -1
- data/config/locales/es.yml +4 -1
- data/config/locales/et.yml +4 -1
- data/config/locales/fa.yml +4 -1
- data/config/locales/fi.yml +4 -1
- data/config/locales/fr.yml +4 -1
- data/config/locales/gd.yml +4 -1
- data/config/locales/gu.yml +4 -1
- data/config/locales/he.yml +4 -1
- data/config/locales/hi.yml +4 -1
- data/config/locales/hr.yml +4 -1
- data/config/locales/hu.yml +4 -1
- data/config/locales/hy.yml +4 -1
- data/config/locales/id.yml +4 -1
- data/config/locales/is.yml +4 -1
- data/config/locales/it.yml +4 -1
- data/config/locales/ja.yml +4 -1
- data/config/locales/ka.yml +4 -1
- data/config/locales/kk.yml +4 -1
- data/config/locales/ko.yml +4 -1
- data/config/locales/lt.yml +4 -1
- data/config/locales/lv.yml +4 -1
- data/config/locales/ms.yml +4 -1
- data/config/locales/mt.yml +4 -1
- data/config/locales/nl.yml +4 -1
- data/config/locales/no.yml +4 -1
- data/config/locales/pa-pk.yml +4 -1
- data/config/locales/pa.yml +4 -1
- data/config/locales/pl.yml +4 -1
- data/config/locales/ps.yml +4 -1
- data/config/locales/pt.yml +4 -1
- data/config/locales/ro.yml +4 -1
- data/config/locales/ru.yml +4 -1
- data/config/locales/si.yml +4 -1
- data/config/locales/sk.yml +4 -1
- data/config/locales/sl.yml +4 -1
- data/config/locales/so.yml +4 -1
- data/config/locales/sq.yml +4 -1
- data/config/locales/sr.yml +4 -1
- data/config/locales/sv.yml +4 -1
- data/config/locales/sw.yml +4 -1
- data/config/locales/ta.yml +4 -1
- data/config/locales/th.yml +4 -1
- data/config/locales/tk.yml +4 -1
- data/config/locales/tr.yml +4 -1
- data/config/locales/uk.yml +4 -1
- data/config/locales/ur.yml +4 -1
- data/config/locales/uz.yml +4 -1
- data/config/locales/vi.yml +4 -1
- data/config/locales/zh-hk.yml +4 -1
- data/config/locales/zh-tw.yml +4 -1
- data/config/locales/zh.yml +4 -1
- data/lib/govuk_publishing_components/presenters/button_helper.rb +7 -1
- data/lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb +25 -1
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/axe-core/axe.js +4567 -4678
- data/node_modules/axe-core/axe.min.js +2 -2
- data/node_modules/axe-core/package.json +2 -2
- data/node_modules/axe-core/sri-history.json +8 -0
- data/node_modules/govuk-frontend/README.md +1 -2
- data/node_modules/govuk-frontend/govuk/all.js +1398 -273
- data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js +70 -0
- data/node_modules/govuk-frontend/govuk/common/index.js +172 -0
- data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js +373 -0
- data/node_modules/govuk-frontend/govuk/common.js +138 -3
- data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js +753 -25
- data/node_modules/govuk-frontend/govuk/components/accordion/fixtures.json +54 -22
- data/node_modules/govuk-frontend/govuk/components/accordion/macro-options.json +36 -0
- data/node_modules/govuk-frontend/govuk/components/accordion/template.njk +7 -1
- data/node_modules/govuk-frontend/govuk/components/back-link/fixtures.json +12 -12
- data/node_modules/govuk-frontend/govuk/components/breadcrumbs/fixtures.json +22 -22
- data/node_modules/govuk-frontend/govuk/components/button/_index.scss +23 -5
- data/node_modules/govuk-frontend/govuk/components/button/button.js +365 -107
- data/node_modules/govuk-frontend/govuk/components/button/fixtures.json +85 -66
- data/node_modules/govuk-frontend/govuk/components/button/template.njk +1 -1
- data/node_modules/govuk-frontend/govuk/components/character-count/_index.scss +9 -0
- data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +1033 -121
- data/node_modules/govuk-frontend/govuk/components/character-count/fixtures.json +112 -36
- data/node_modules/govuk-frontend/govuk/components/character-count/macro-options.json +42 -0
- data/node_modules/govuk-frontend/govuk/components/character-count/template.njk +27 -3
- data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js +30 -2
- data/node_modules/govuk-frontend/govuk/components/checkboxes/fixtures.json +96 -93
- data/node_modules/govuk-frontend/govuk/components/cookie-banner/fixtures.json +46 -46
- data/node_modules/govuk-frontend/govuk/components/date-input/fixtures.json +50 -50
- data/node_modules/govuk-frontend/govuk/components/details/details.js +43 -13
- data/node_modules/govuk-frontend/govuk/components/details/fixtures.json +20 -20
- data/node_modules/govuk-frontend/govuk/components/error-message/fixtures.json +20 -20
- data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js +268 -6
- data/node_modules/govuk-frontend/govuk/components/error-summary/fixtures.json +44 -35
- data/node_modules/govuk-frontend/govuk/components/error-summary/template.njk +25 -21
- data/node_modules/govuk-frontend/govuk/components/fieldset/fixtures.json +51 -39
- data/node_modules/govuk-frontend/govuk/components/file-upload/fixtures.json +26 -26
- data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +1 -1
- data/node_modules/govuk-frontend/govuk/components/footer/fixtures.json +46 -46
- data/node_modules/govuk-frontend/govuk/components/footer/macro-options.json +2 -2
- data/node_modules/govuk-frontend/govuk/components/header/fixtures.json +93 -38
- data/node_modules/govuk-frontend/govuk/components/header/header.js +6 -0
- data/node_modules/govuk-frontend/govuk/components/header/macro-options.json +8 -2
- data/node_modules/govuk-frontend/govuk/components/header/template.njk +4 -2
- data/node_modules/govuk-frontend/govuk/components/hint/fixtures.json +12 -12
- data/node_modules/govuk-frontend/govuk/components/input/fixtures.json +80 -80
- data/node_modules/govuk-frontend/govuk/components/inset-text/fixtures.json +12 -12
- data/node_modules/govuk-frontend/govuk/components/label/fixtures.json +34 -34
- data/node_modules/govuk-frontend/govuk/components/notification-banner/fixtures.json +56 -46
- data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js +252 -2
- data/node_modules/govuk-frontend/govuk/components/notification-banner/template.njk +1 -1
- data/node_modules/govuk-frontend/govuk/components/pagination/_index.scss +10 -7
- data/node_modules/govuk-frontend/govuk/components/pagination/fixtures.json +33 -26
- data/node_modules/govuk-frontend/govuk/components/panel/fixtures.json +18 -18
- data/node_modules/govuk-frontend/govuk/components/phase-banner/fixtures.json +14 -14
- data/node_modules/govuk-frontend/govuk/components/radios/fixtures.json +94 -91
- data/node_modules/govuk-frontend/govuk/components/radios/radios.js +30 -2
- data/node_modules/govuk-frontend/govuk/components/select/fixtures.json +32 -32
- data/node_modules/govuk-frontend/govuk/components/skip-link/fixtures.json +22 -20
- data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js +10 -4
- data/node_modules/govuk-frontend/govuk/components/summary-list/fixtures.json +50 -50
- data/node_modules/govuk-frontend/govuk/components/table/_index.scss +1 -1
- data/node_modules/govuk-frontend/govuk/components/table/fixtures.json +40 -40
- data/node_modules/govuk-frontend/govuk/components/tabs/fixtures.json +29 -29
- data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js +28 -0
- data/node_modules/govuk-frontend/govuk/components/tag/fixtures.json +28 -28
- data/node_modules/govuk-frontend/govuk/components/textarea/fixtures.json +34 -34
- data/node_modules/govuk-frontend/govuk/components/warning-text/fixtures.json +14 -14
- data/node_modules/govuk-frontend/govuk/core/_section-break.scss +1 -1
- data/node_modules/govuk-frontend/govuk/helpers/_colour.scss +2 -2
- data/node_modules/govuk-frontend/govuk/helpers/_links.scss +6 -6
- data/node_modules/govuk-frontend/govuk/i18n.js +390 -0
- data/node_modules/govuk-frontend/govuk/macros/i18n.njk +15 -0
- data/node_modules/govuk-frontend/govuk/settings/_all.scss +1 -0
- data/node_modules/govuk-frontend/govuk/settings/_colours-palette.scss +12 -0
- data/node_modules/govuk-frontend/govuk/settings/_compatibility.scss +26 -0
- data/node_modules/govuk-frontend/govuk/settings/_typography-font.scss +23 -0
- data/node_modules/govuk-frontend/govuk/settings/_typography-responsive.scss +12 -0
- data/node_modules/govuk-frontend/govuk/settings/_warnings.scss +53 -0
- data/node_modules/govuk-frontend/govuk/tools/_compatibility.scss +20 -6
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js +21 -0
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js +300 -0
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js +21 -0
- data/node_modules/govuk-frontend/govuk-esm/all.mjs +50 -27
- data/node_modules/govuk-frontend/govuk-esm/common/closest-attribute-value.mjs +15 -0
- data/node_modules/govuk-frontend/govuk-esm/common/index.mjs +159 -0
- data/node_modules/govuk-frontend/govuk-esm/common/normalise-dataset.mjs +58 -0
- data/node_modules/govuk-frontend/govuk-esm/common.mjs +6 -28
- data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs +113 -43
- data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs +67 -30
- data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs +325 -123
- data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs +9 -3
- data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs +22 -8
- data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs +48 -6
- data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs +6 -0
- data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs +32 -2
- data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs +9 -3
- data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs +10 -4
- data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs +8 -2
- data/node_modules/govuk-frontend/govuk-esm/i18n.mjs +380 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Date/now.mjs +13 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/dataset.mjs +68 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/String/prototype/trim.mjs +13 -0
- data/node_modules/govuk-frontend/govuk-prototype-kit/init.js +7 -0
- data/node_modules/govuk-frontend/govuk-prototype-kit/init.scss +12 -0
- data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +138 -7
- data/node_modules/govuk-frontend/package.json +1 -1
- metadata +22 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72c594630cfc9f9359ae29eaff51094d512f4060cff0ad23e96319f264b0bae6
|
4
|
+
data.tar.gz: d074f64d7b59bd3657e0e84c2a44f9de23a8a5db99e71e832b2eab98a617fb8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77cde1c322a721bc97a30a348e53b84d369c029afa32cd81fc7def30577aea67324f4c60ecc5c6f03e1c77dc3697d6a2ab5339a177c3946276ddcaa26bb72303
|
7
|
+
data.tar.gz: 7134f8030b4d16a4b4e38dc5ba6aa8d9c08aa0bc2ef319e7710b407685a8cbace2ce9c32c5330883cd93412690687387f5960246667a63a8808cc20949c02de1
|
@@ -1,3 +1,4 @@
|
|
1
|
+
//= require ../vendor/polyfills/closest.js
|
1
2
|
window.GOVUK = window.GOVUK || {}
|
2
3
|
window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
|
3
4
|
|
@@ -47,6 +48,180 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
|
|
47
48
|
|
48
49
|
getGemVersion: function () {
|
49
50
|
return window.GOVUK.analyticsGa4.vars.gem_version || 'not found'
|
51
|
+
},
|
52
|
+
|
53
|
+
trackFunctions: {
|
54
|
+
findTrackingAttributes: function (clicked, trackingTrigger) {
|
55
|
+
if (clicked.hasAttribute('[' + trackingTrigger + ']')) {
|
56
|
+
return clicked
|
57
|
+
} else {
|
58
|
+
return clicked.closest('[' + trackingTrigger + ']')
|
59
|
+
}
|
60
|
+
},
|
61
|
+
|
62
|
+
// create an object to split up long URLs and get around the 100 character limit on GTM data
|
63
|
+
// this gets reassembled in GA4
|
64
|
+
populateLinkPathParts: function (href) {
|
65
|
+
var path = ''
|
66
|
+
if (this.hrefIsRelative(href) || this.isMailToLink(href)) {
|
67
|
+
path = href
|
68
|
+
} else {
|
69
|
+
// This regex matches a protocol and domain name at the start of a string such as https://www.gov.uk, http://gov.uk, //gov.uk
|
70
|
+
path = href.replace(/^(http:||https:)?(\/\/)([^\/]*)/, '') // eslint-disable-line no-useless-escape
|
71
|
+
}
|
72
|
+
|
73
|
+
if (path === '/' || path.length === 0) {
|
74
|
+
return
|
75
|
+
}
|
76
|
+
|
77
|
+
/*
|
78
|
+
This will create an object with 5 keys that are indexes ("1", "2", etc.)
|
79
|
+
The values will be each part of the link path split every 100 characters, or undefined.
|
80
|
+
For example: {"1": "/hello/world/etc...", "2": "/more/path/text...", "3": undefined, "4": undefined, "5": undefined}
|
81
|
+
Undefined values are needed to override the persistent object in GTM so that any values from old pushes are overwritten.
|
82
|
+
*/
|
83
|
+
var parts = path.match(/.{1,100}/g)
|
84
|
+
var obj = {}
|
85
|
+
for (var i = 0; i < 5; i++) {
|
86
|
+
obj[(i + 1).toString()] = parts[i]
|
87
|
+
}
|
88
|
+
return obj
|
89
|
+
},
|
90
|
+
|
91
|
+
hrefIsRelative: function (href) {
|
92
|
+
// Checks that a link is relative, but is not a protocol relative url
|
93
|
+
return href[0] === '/' && href[1] !== '/'
|
94
|
+
},
|
95
|
+
|
96
|
+
hrefIsAnchor: function (href) {
|
97
|
+
return href[0] === '#'
|
98
|
+
},
|
99
|
+
|
100
|
+
isMailToLink: function (href) {
|
101
|
+
return href.substring(0, 7) === 'mailto:'
|
102
|
+
},
|
103
|
+
|
104
|
+
getClickType: function (event) {
|
105
|
+
switch (event.type) {
|
106
|
+
case 'click':
|
107
|
+
if (event.ctrlKey) {
|
108
|
+
return 'ctrl click'
|
109
|
+
} else if (event.metaKey) {
|
110
|
+
return 'command/win click'
|
111
|
+
} else if (event.shiftKey) {
|
112
|
+
return 'shift click'
|
113
|
+
} else {
|
114
|
+
return 'primary click'
|
115
|
+
}
|
116
|
+
case 'mousedown':
|
117
|
+
return 'middle click'
|
118
|
+
case 'contextmenu':
|
119
|
+
return 'secondary click'
|
120
|
+
}
|
121
|
+
},
|
122
|
+
|
123
|
+
isInternalLink: function (href) {
|
124
|
+
var internalDomains = window.GOVUK.analyticsGa4.vars.internalDomains
|
125
|
+
if (this.hrefIsRelative(href) || this.hrefIsAnchor(href)) {
|
126
|
+
return true
|
127
|
+
}
|
128
|
+
var result = false
|
129
|
+
for (var i = 0; i < internalDomains.length; i++) {
|
130
|
+
var internalDomain = internalDomains[i]
|
131
|
+
if (this.hrefPointsToDomain(href, internalDomain)) {
|
132
|
+
result = true
|
133
|
+
}
|
134
|
+
}
|
135
|
+
return result
|
136
|
+
},
|
137
|
+
|
138
|
+
isExternalLink: function (href) {
|
139
|
+
return !this.isInternalLink(href)
|
140
|
+
},
|
141
|
+
|
142
|
+
hrefPointsToDomain: function (href, domain) {
|
143
|
+
/* Add a trailing slash to prevent an edge case such
|
144
|
+
as the href www.gov.uk.domain.co.uk being detected as an internal link,
|
145
|
+
if we were checking for 'www.gov.uk' instead of 'www.gov.uk/' */
|
146
|
+
if (domain.substring(domain.length) !== '/') {
|
147
|
+
domain = domain + '/'
|
148
|
+
}
|
149
|
+
|
150
|
+
/* If the href doesn't end in a slash, we add one.
|
151
|
+
This fixes an edge case where the <a href> is exactly `https://www.gov.uk`
|
152
|
+
but these checks would only look for `https://www.gov.uk/` */
|
153
|
+
if (href.substring(href.length) !== '/') {
|
154
|
+
href = href + '/'
|
155
|
+
}
|
156
|
+
// matches the domain preceded by https:// http:// or //
|
157
|
+
var regex = new RegExp('^((http)*(s)*(:)*//)(' + domain + ')', 'g')
|
158
|
+
return regex.test(href)
|
159
|
+
},
|
160
|
+
|
161
|
+
removeLinesAndExtraSpaces: function (text) {
|
162
|
+
text = text.trim()
|
163
|
+
text = text.replace(/(\r\n|\n|\r)/gm, ' ') // Replace line breaks with 1 space
|
164
|
+
text = text.replace(/\s+/g, ' ') // Replace instances of 2+ spaces with 1 space
|
165
|
+
return text
|
166
|
+
},
|
167
|
+
|
168
|
+
removeCrossDomainParams: function (href) {
|
169
|
+
if (href.indexOf('_ga') !== -1 || href.indexOf('_gl') !== -1) {
|
170
|
+
// _ga & _gl are values needed for cross domain tracking, but we don't want them included in our click tracking.
|
171
|
+
href = href.replaceAll(/_g[al]=([^&]*)/g, '')
|
172
|
+
|
173
|
+
// The following code cleans up inconsistencies such as gov.uk/&&, gov.uk/?&hello=world, gov.uk/?, and gov.uk/&.
|
174
|
+
href = href.replaceAll(/(&&)+/g, '&')
|
175
|
+
href = href.replace('?&', '?')
|
176
|
+
if (this.stringEndsWith(href, '?') || this.stringEndsWith(href, '&')) {
|
177
|
+
href = href.substring(0, href.length - 1)
|
178
|
+
}
|
179
|
+
}
|
180
|
+
return href
|
181
|
+
},
|
182
|
+
|
183
|
+
stringStartsWith: function (string, stringToFind) {
|
184
|
+
return string.substring(0, stringToFind.length) === stringToFind
|
185
|
+
},
|
186
|
+
|
187
|
+
stringEndsWith: function (string, stringToFind) {
|
188
|
+
return string.substring(string.length - stringToFind.length, string.length) === stringToFind
|
189
|
+
},
|
190
|
+
|
191
|
+
populateLinkDomain: function (href) {
|
192
|
+
// We always want mailto links to have an undefined link_domain
|
193
|
+
if (this.isMailToLink(href)) {
|
194
|
+
return undefined
|
195
|
+
}
|
196
|
+
|
197
|
+
if (this.hrefIsRelative(href) || this.hrefIsAnchor(href)) {
|
198
|
+
return this.getProtocol() + '//' + this.getHostname()
|
199
|
+
} else {
|
200
|
+
// This regex matches a protocol and domain name at the start of a string such as https://www.gov.uk, http://gov.uk, //gov.uk
|
201
|
+
var domainRegex = /^(http:||https:)?(\/\/)([^\/]*)/ // eslint-disable-line no-useless-escape
|
202
|
+
var domain = domainRegex.exec(href)[0]
|
203
|
+
return domain
|
204
|
+
}
|
205
|
+
},
|
206
|
+
|
207
|
+
getProtocol: function () {
|
208
|
+
return window.location.protocol
|
209
|
+
},
|
210
|
+
|
211
|
+
getHostname: function () {
|
212
|
+
return window.location.hostname
|
213
|
+
},
|
214
|
+
|
215
|
+
appendDomainsWithoutWWW: function (domainsArrays) {
|
216
|
+
// Add domains with www. removed, in case site hrefs are marked up without www. included.
|
217
|
+
for (var i = 0; i < domainsArrays.length; i++) {
|
218
|
+
var domain = domainsArrays[i]
|
219
|
+
if (this.stringStartsWith(domain, 'www.')) {
|
220
|
+
var domainWithoutWww = domain.replace('www.', '')
|
221
|
+
domainsArrays.push(domainWithoutWww)
|
222
|
+
}
|
223
|
+
}
|
224
|
+
}
|
50
225
|
}
|
51
226
|
}
|
52
227
|
|
data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-ecommerce-tracker.js
CHANGED
@@ -97,7 +97,7 @@
|
|
97
97
|
})
|
98
98
|
|
99
99
|
ecommerceObject.event_data = {
|
100
|
-
external: GOVUK.analyticsGa4.
|
100
|
+
external: GOVUK.analyticsGa4.core.trackFunctions.isExternalLink(searchResult.getAttribute('data-ecommerce-path')) ? 'true' : 'false'
|
101
101
|
}
|
102
102
|
} else {
|
103
103
|
for (var i = 0; i < ecommerceRows.length; i++) {
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
//= require ../vendor/polyfills/closest.js
|
2
2
|
window.GOVUK = window.GOVUK || {}
|
3
3
|
window.GOVUK.Modules = window.GOVUK.Modules || {};
|
4
4
|
|
@@ -7,7 +7,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
|
|
7
7
|
|
8
8
|
function Ga4EventTracker (module) {
|
9
9
|
this.module = module
|
10
|
-
this.trackingTrigger = 'data-ga4' // elements with this attribute get tracked
|
10
|
+
this.trackingTrigger = 'data-ga4-event' // elements with this attribute get tracked
|
11
11
|
}
|
12
12
|
|
13
13
|
Ga4EventTracker.prototype.init = function () {
|
@@ -29,7 +29,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
|
|
29
29
|
}
|
30
30
|
|
31
31
|
Ga4EventTracker.prototype.trackClick = function (event) {
|
32
|
-
var target =
|
32
|
+
var target = window.GOVUK.analyticsGa4.core.trackFunctions.findTrackingAttributes(event.target, this.trackingTrigger)
|
33
33
|
if (target) {
|
34
34
|
var schema = new window.GOVUK.analyticsGa4.Schemas().eventSchema()
|
35
35
|
|
@@ -51,8 +51,8 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
|
|
51
51
|
}
|
52
52
|
}
|
53
53
|
|
54
|
-
/* Ensure it only tracks aria-expanded in an
|
55
|
-
if (target.closest('
|
54
|
+
/* Ensure it only tracks aria-expanded in an element with data-ga4-expandable on it. */
|
55
|
+
if (target.closest('[data-ga4-expandable]')) {
|
56
56
|
var ariaExpanded = this.getClosestAttribute(target, 'aria-expanded')
|
57
57
|
}
|
58
58
|
|
@@ -88,14 +88,6 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
|
|
88
88
|
}
|
89
89
|
}
|
90
90
|
|
91
|
-
Ga4EventTracker.prototype.findTrackingAttributes = function (clicked) {
|
92
|
-
if (clicked.hasAttribute('[' + this.trackingTrigger + ']')) {
|
93
|
-
return clicked
|
94
|
-
} else {
|
95
|
-
return clicked.closest('[' + this.trackingTrigger + ']')
|
96
|
-
}
|
97
|
-
}
|
98
|
-
|
99
91
|
// check if an attribute exists or contains the attribute
|
100
92
|
Ga4EventTracker.prototype.getClosestAttribute = function (clicked, attribute) {
|
101
93
|
var isAttributeOnElement = clicked.getAttribute(attribute)
|
@@ -1,331 +1,102 @@
|
|
1
|
-
|
1
|
+
//= require ../vendor/polyfills/closest.js
|
2
2
|
window.GOVUK = window.GOVUK || {}
|
3
|
-
window.GOVUK.
|
4
|
-
window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analyticsModules || {};
|
3
|
+
window.GOVUK.Modules = window.GOVUK.Modules || {};
|
5
4
|
|
6
|
-
(function (
|
5
|
+
(function (Modules) {
|
7
6
|
'use strict'
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
this.appendDomainsWithoutWWW(this.internalDomains)
|
16
|
-
this.internalDownloadPaths = config.internalDownloadPaths || ['/government/uploads/']
|
17
|
-
this.dedicatedDownloadDomains = config.dedicatedDownloadDomains || ['assets.publishing.service.gov.uk']
|
18
|
-
this.appendDomainsWithoutWWW(this.dedicatedDownloadDomains)
|
19
|
-
this.handleClick = this.handleClick.bind(this)
|
20
|
-
this.handleMousedown = this.handleMousedown.bind(this)
|
21
|
-
|
22
|
-
if (!config.disableListeners) {
|
23
|
-
document.querySelector('body').addEventListener('click', this.handleClick)
|
24
|
-
document.querySelector('body').addEventListener('contextmenu', this.handleClick)
|
25
|
-
document.querySelector('body').addEventListener('mousedown', this.handleMousedown)
|
26
|
-
}
|
27
|
-
}
|
28
|
-
},
|
29
|
-
|
30
|
-
stopTracking: function () {
|
31
|
-
document.querySelector('body').removeEventListener('click', this.handleClick)
|
32
|
-
document.querySelector('body').removeEventListener('contextmenu', this.handleClick)
|
33
|
-
document.querySelector('body').removeEventListener('mousedown', this.handleMousedown)
|
34
|
-
},
|
35
|
-
|
36
|
-
handleClick: function (event) {
|
37
|
-
var element = event.target
|
38
|
-
|
39
|
-
if (element.tagName !== 'A') {
|
40
|
-
element = element.closest('a')
|
41
|
-
}
|
42
|
-
|
43
|
-
if (!element) {
|
44
|
-
return
|
45
|
-
}
|
46
|
-
|
47
|
-
var href = element.getAttribute('href')
|
48
|
-
|
49
|
-
if (!href) {
|
50
|
-
return
|
51
|
-
}
|
52
|
-
var clickData = {}
|
53
|
-
var linkAttributes = element.getAttribute('data-ga4-link')
|
54
|
-
if (linkAttributes) {
|
55
|
-
clickData = JSON.parse(linkAttributes)
|
56
|
-
|
57
|
-
/* Since external links can't be determined in the template, we use populated-via-js as a signal
|
58
|
-
for our JavaScript to determine this value. */
|
59
|
-
if (clickData.external === 'populated-via-js' && clickData.url) {
|
60
|
-
clickData.external = this.isExternalLink(clickData.url) ? 'true' : 'false'
|
61
|
-
}
|
62
|
-
|
63
|
-
if (clickData.method === 'populated-via-js') {
|
64
|
-
clickData.method = this.getClickType(event)
|
65
|
-
}
|
66
|
-
|
67
|
-
if (clickData.index) {
|
68
|
-
clickData.index = parseInt(clickData.index)
|
69
|
-
}
|
8
|
+
function Ga4LinkTracker (module) {
|
9
|
+
this.module = module
|
10
|
+
this.trackingTrigger = 'data-ga4-link' // elements with this attribute get tracked
|
11
|
+
this.trackLinksOnly = this.module.hasAttribute('data-ga4-track-links-only')
|
12
|
+
this.limitToElementClass = this.module.getAttribute('data-ga4-limit-to-element-class')
|
13
|
+
}
|
70
14
|
|
71
|
-
|
72
|
-
|
73
|
-
}
|
74
|
-
} else if (this.isMailToLink(href)) {
|
75
|
-
clickData.event_name = 'navigation'
|
76
|
-
clickData.type = 'email'
|
77
|
-
clickData.external = 'true'
|
78
|
-
clickData.url = href
|
79
|
-
clickData.text = this.removeLinesAndExtraSpaces(element.textContent)
|
80
|
-
clickData.method = this.getClickType(event)
|
81
|
-
} else if (this.isDownloadLink(href)) {
|
82
|
-
clickData.event_name = 'file_download'
|
83
|
-
clickData.type = this.isPreviewLink(href) ? 'preview' : 'generic download'
|
84
|
-
clickData.external = this.isExternalLink(href) ? 'true' : 'false'
|
85
|
-
clickData.url = href
|
86
|
-
clickData.text = this.removeLinesAndExtraSpaces(element.textContent)
|
87
|
-
clickData.method = this.getClickType(event)
|
88
|
-
} else if (this.isExternalLink(href)) {
|
89
|
-
clickData.event_name = 'navigation'
|
90
|
-
clickData.type = 'generic link'
|
91
|
-
clickData.external = 'true'
|
92
|
-
clickData.url = href
|
93
|
-
clickData.text = this.removeLinesAndExtraSpaces(element.textContent)
|
94
|
-
clickData.method = this.getClickType(event)
|
95
|
-
}
|
15
|
+
Ga4LinkTracker.prototype.init = function () {
|
16
|
+
var consentCookie = window.GOVUK.getConsentCookie()
|
96
17
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
18
|
+
if (consentCookie && consentCookie.settings) {
|
19
|
+
this.startModule()
|
20
|
+
} else {
|
21
|
+
this.startModule = this.startModule.bind(this)
|
22
|
+
window.addEventListener('cookie-consent', this.startModule)
|
23
|
+
}
|
24
|
+
}
|
103
25
|
|
104
|
-
|
105
|
-
|
26
|
+
// triggered by cookie-consent event, which happens when users consent to cookies
|
27
|
+
Ga4LinkTracker.prototype.startModule = function () {
|
28
|
+
if (window.dataLayer) {
|
29
|
+
this.handleClick = this.handleClick.bind(this)
|
30
|
+
this.handleMousedown = this.handleMousedown.bind(this)
|
106
31
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
}
|
113
|
-
}
|
32
|
+
this.module.addEventListener('click', this.handleClick)
|
33
|
+
this.module.addEventListener('contextmenu', this.handleClick)
|
34
|
+
this.module.addEventListener('mousedown', this.handleMousedown)
|
35
|
+
}
|
36
|
+
}
|
114
37
|
|
115
|
-
|
38
|
+
Ga4LinkTracker.prototype.handleClick = function (event) {
|
39
|
+
var target = event.target
|
40
|
+
if (!this.trackLinksOnly) {
|
41
|
+
this.trackClick(event)
|
42
|
+
} else if (this.trackLinksOnly && target.closest('a')) {
|
43
|
+
if (!this.limitToElementClass) {
|
44
|
+
this.trackClick(event)
|
45
|
+
} else if (target.closest('.' + this.limitToElementClass)) {
|
46
|
+
this.trackClick(event)
|
116
47
|
}
|
117
|
-
}
|
48
|
+
}
|
49
|
+
}
|
118
50
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
path = href.replace(/^(http:||https:)?(\/\/)([^\/]*)/, '') // eslint-disable-line no-useless-escape
|
126
|
-
}
|
51
|
+
Ga4LinkTracker.prototype.handleMousedown = function (event) {
|
52
|
+
// 1 = middle mouse button
|
53
|
+
if (event.button === 1) {
|
54
|
+
this.handleClick(event)
|
55
|
+
}
|
56
|
+
}
|
127
57
|
|
128
|
-
|
58
|
+
Ga4LinkTracker.prototype.trackClick = function (event) {
|
59
|
+
var target = window.GOVUK.analyticsGa4.core.trackFunctions.findTrackingAttributes(event.target, this.trackingTrigger)
|
60
|
+
if (target) {
|
61
|
+
var schema = new window.GOVUK.analyticsGa4.Schemas().eventSchema()
|
62
|
+
|
63
|
+
try {
|
64
|
+
var data = target.getAttribute(this.trackingTrigger)
|
65
|
+
data = JSON.parse(data)
|
66
|
+
} catch (e) {
|
67
|
+
// if there's a problem with the config, don't start the tracker
|
68
|
+
console.error('GA4 configuration error: ' + e.message, window.location)
|
129
69
|
return
|
130
70
|
}
|
131
71
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
populateLinkDomain: function (href) {
|
147
|
-
// We always want mailto links to have an undefined link_domain
|
148
|
-
if (this.isMailToLink(href)) {
|
149
|
-
return undefined
|
150
|
-
}
|
151
|
-
|
152
|
-
if (this.hrefIsRelative(href)) {
|
153
|
-
return this.getProtocol() + '//' + this.getHostname()
|
154
|
-
} else {
|
155
|
-
// This regex matches a protocol and domain name at the start of a string such as https://www.gov.uk, http://gov.uk, //gov.uk
|
156
|
-
var domainRegex = /^(http:||https:)?(\/\/)([^\/]*)/ // eslint-disable-line no-useless-escape
|
157
|
-
var domain = domainRegex.exec(href)[0]
|
158
|
-
return domain
|
159
|
-
}
|
160
|
-
},
|
161
|
-
|
162
|
-
appendDomainsWithoutWWW: function (domainsArrays) {
|
163
|
-
// Add domains with www. removed, in case site hrefs are marked up without www. included.
|
164
|
-
for (var i = 0; i < domainsArrays.length; i++) {
|
165
|
-
var domain = domainsArrays[i]
|
166
|
-
if (this.stringStartsWith(domain, 'www.')) {
|
167
|
-
var domainWithoutWww = domain.replace('www.', '')
|
168
|
-
domainsArrays.push(domainWithoutWww)
|
72
|
+
schema.event = 'event_data'
|
73
|
+
var text = data.text || event.target.textContent
|
74
|
+
data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(text)
|
75
|
+
data.url = window.GOVUK.analyticsGa4.core.trackFunctions.removeCrossDomainParams(this.findLink(event.target).getAttribute('href'))
|
76
|
+
data.link_domain = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkDomain(data.url)
|
77
|
+
data.link_path_parts = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkPathParts(data.url)
|
78
|
+
data.method = window.GOVUK.analyticsGa4.core.trackFunctions.getClickType(event)
|
79
|
+
data.external = window.GOVUK.analyticsGa4.core.trackFunctions.isExternalLink(data.url) ? 'true' : 'false'
|
80
|
+
|
81
|
+
// get attributes from the data attribute to send to GA
|
82
|
+
// only allow it if it already exists in the schema
|
83
|
+
for (var property in data) {
|
84
|
+
if (property in schema.event_data) {
|
85
|
+
schema.event_data[property] = data[property]
|
169
86
|
}
|
170
87
|
}
|
171
|
-
},
|
172
|
-
|
173
|
-
removeLinesAndExtraSpaces: function (text) {
|
174
|
-
text = text.trim()
|
175
|
-
text = text.replace(/(\r\n|\n|\r)/gm, ' ') // Replace line breaks with 1 space
|
176
|
-
text = text.replace(/\s+/g, ' ') // Replace instances of 2+ spaces with 1 space
|
177
|
-
return text
|
178
|
-
},
|
179
|
-
|
180
|
-
getClickType: function (event) {
|
181
|
-
switch (event.type) {
|
182
|
-
case 'click':
|
183
|
-
if (event.ctrlKey) {
|
184
|
-
return 'ctrl click'
|
185
|
-
} else if (event.metaKey) {
|
186
|
-
return 'command/win click'
|
187
|
-
} else if (event.shiftKey) {
|
188
|
-
return 'shift click'
|
189
|
-
} else {
|
190
|
-
return 'primary click'
|
191
|
-
}
|
192
|
-
case 'mousedown':
|
193
|
-
return 'middle click'
|
194
|
-
case 'contextmenu':
|
195
|
-
return 'secondary click'
|
196
|
-
}
|
197
|
-
},
|
198
|
-
|
199
|
-
handleMousedown: function (event) {
|
200
|
-
// 1 = middle mouse button
|
201
|
-
if (event.button === 1) {
|
202
|
-
this.handleClick(event)
|
203
|
-
}
|
204
|
-
},
|
205
|
-
|
206
|
-
isMailToLink: function (href) {
|
207
|
-
return href.substring(0, 7) === 'mailto:'
|
208
|
-
},
|
209
|
-
|
210
|
-
isDownloadLink: function (href) {
|
211
|
-
if (this.isInternalLink(href) && this.hrefPointsToDownloadPath(href)) {
|
212
|
-
return true
|
213
|
-
}
|
214
|
-
|
215
|
-
var result = false
|
216
|
-
for (var i = 0; i < this.dedicatedDownloadDomains.length; i++) {
|
217
|
-
var downloadDomain = this.dedicatedDownloadDomains[i]
|
218
|
-
if (this.hrefPointsToDomain(href, downloadDomain)) {
|
219
|
-
result = true
|
220
|
-
}
|
221
|
-
}
|
222
|
-
return result
|
223
|
-
},
|
224
|
-
|
225
|
-
isInternalLink: function (href) {
|
226
|
-
if (this.hrefIsRelative(href) || this.hrefIsAnchor(href)) {
|
227
|
-
return true
|
228
|
-
}
|
229
|
-
var result = false
|
230
|
-
for (var i = 0; i < this.internalDomains.length; i++) {
|
231
|
-
var internalDomain = this.internalDomains[i]
|
232
|
-
if (this.hrefPointsToDomain(href, internalDomain)) {
|
233
|
-
result = true
|
234
|
-
}
|
235
|
-
}
|
236
|
-
return result
|
237
|
-
},
|
238
|
-
|
239
|
-
isExternalLink: function (href) {
|
240
|
-
return !this.isInternalLink(href)
|
241
|
-
},
|
242
88
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
2. any alphanumeric characters (so we can match any file type such as jpg, pdf, mp4.)
|
247
|
-
3. the presence of '/preview'.
|
248
|
-
For example, .csv/preview or .mp4/preview will be matched.
|
249
|
-
Regex is used over JS string methods as this should work with anchor links, query string parameters and files that may have 'preview' in their name.
|
250
|
-
*/
|
251
|
-
var previewRegex = /\.\w+\/preview/i
|
252
|
-
return previewRegex.test(href)
|
253
|
-
},
|
254
|
-
|
255
|
-
hrefPointsToDomain: function (href, domain) {
|
256
|
-
/* Add a trailing slash to prevent an edge case such
|
257
|
-
as the href www.gov.uk.domain.co.uk being detected as an internal link,
|
258
|
-
if we were checking for 'www.gov.uk' instead of 'www.gov.uk/' */
|
259
|
-
if (domain.substring(domain.length) !== '/') {
|
260
|
-
domain = domain + '/'
|
261
|
-
}
|
262
|
-
|
263
|
-
/* If the href doesn't end in a slash, we add one.
|
264
|
-
This fixes an edge case where the <a href> is exactly `https://www.gov.uk`
|
265
|
-
but these checks would only look for `https://www.gov.uk/` */
|
266
|
-
if (href.substring(href.length) !== '/') {
|
267
|
-
href = href + '/'
|
268
|
-
}
|
269
|
-
var httpDomain = 'http://' + domain
|
270
|
-
var httpsDomain = 'https://' + domain
|
271
|
-
var schemaRelativeDomain = '//' + domain
|
272
|
-
return this.stringStartsWith(href, domain) ||
|
273
|
-
this.stringStartsWith(href, httpDomain) ||
|
274
|
-
this.stringStartsWith(href, httpsDomain) ||
|
275
|
-
this.stringStartsWith(href, schemaRelativeDomain)
|
276
|
-
},
|
277
|
-
|
278
|
-
hrefPointsToDownloadPath: function (href) {
|
279
|
-
var result = false
|
280
|
-
for (var i = 0; i < this.internalDownloadPaths.length; i++) {
|
281
|
-
var internalDownloadPath = this.internalDownloadPaths[i]
|
282
|
-
if (href.indexOf(internalDownloadPath) !== -1) {
|
283
|
-
result = true
|
284
|
-
}
|
285
|
-
}
|
286
|
-
return result
|
287
|
-
},
|
288
|
-
|
289
|
-
stringStartsWith: function (string, stringToFind) {
|
290
|
-
return string.substring(0, stringToFind.length) === stringToFind
|
291
|
-
},
|
292
|
-
|
293
|
-
stringEndsWith: function (string, stringToFind) {
|
294
|
-
return string.substring(string.length - stringToFind.length, string.length) === stringToFind
|
295
|
-
},
|
296
|
-
|
297
|
-
hrefIsRelative: function (href) {
|
298
|
-
// Checks that a link is relative, but is not a protocol relative url
|
299
|
-
return href[0] === '/' && href[1] !== '/'
|
300
|
-
},
|
301
|
-
|
302
|
-
hrefIsAnchor: function (href) {
|
303
|
-
return href[0] === '#'
|
304
|
-
},
|
305
|
-
|
306
|
-
getHostname: function () {
|
307
|
-
return window.location.hostname
|
308
|
-
},
|
309
|
-
|
310
|
-
getProtocol: function () {
|
311
|
-
return window.location.protocol
|
312
|
-
},
|
313
|
-
|
314
|
-
removeCrossDomainParams: function (href) {
|
315
|
-
if (href.indexOf('_ga') !== -1 || href.indexOf('_gl') !== -1) {
|
316
|
-
// _ga & _gl are values needed for cross domain tracking, but we don't want them included in our click tracking.
|
317
|
-
href = href.replaceAll(/_g[al]=([^&]*)/g, '')
|
89
|
+
window.GOVUK.analyticsGa4.core.sendData(schema)
|
90
|
+
}
|
91
|
+
}
|
318
92
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
}
|
325
|
-
}
|
326
|
-
return href
|
93
|
+
Ga4LinkTracker.prototype.findLink = function (target) {
|
94
|
+
if (target.tagName === 'A') {
|
95
|
+
return target
|
96
|
+
} else {
|
97
|
+
return target.closest('a')
|
327
98
|
}
|
328
99
|
}
|
329
100
|
|
330
|
-
|
331
|
-
})(window.GOVUK.
|
101
|
+
Modules.Ga4LinkTracker = Ga4LinkTracker
|
102
|
+
})(window.GOVUK.Modules)
|