Skip to content

Commit d925b36

Browse files
0xDanomiteDan McQuillan
andauthored
Fix: update metrics collection banner to modal with management toggle settings (#373)
* fix: 340 - updates to add modal and toggles for telemetry consent * fix: 340 updated metrics consent text * fix - 340 updated linter issues * feat - 340 toggle modal redesign, updates to modal design per pr * fix: 340 - updated metrics countly to minimal for default * fix: 340 - updated styles file for linting error Co-authored-by: Dan McQuillan <[email protected]>
1 parent a81d48b commit d925b36

File tree

4 files changed

+337
-150
lines changed

4 files changed

+337
-150
lines changed

src/countly.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ declare module 'countly-sdk-web' {
2727
interface CountlyWebSdk {
2828
group_features: (arg0: Record<string, string[]>) => unknown
2929
add_consent: (consentFeature: string | string[]) => void
30+
remove_consent: (consentFeature: string | string[]) => void
3031
require_consent: boolean
3132
init: (configOptions?: Partial<CountlyWebSdk>) => void
3233
/**

src/index.html

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -60,41 +60,64 @@ <h1 class='f3 fw2 montserrat aqua ttu ma0'>Public Gateways</h1>
6060
<div class="Took">ΔT</div>
6161
</div>
6262
</div>
63-
<div class="hidden js-metrics-notification-decline-warning metrics-notification-wrapper bg-navy bt bw1 border-aqua">
64-
<div class="metrics-notification-spacer"></div>
65-
<div class="metrics-notification-container">
66-
<span id="metrics-notification-decline-warning" class="metrics-notification-text">
67-
We will limit collection of metrics to only necessary features, 'sessions' and 'views'. See <a href="https://support.count.ly/hc/en-us/articles/360037441932-Web-analytics-JavaScript-#features-for-consent">Countly's group_features</a> for more information.
63+
64+
<div class="hidden js-metrics-notification-modal metrics-notification-wrapper bg-navy bt bw1 border-jade">
65+
<div class="metrics-modal-close js-modal-close"></div>
66+
<div class="metrics-notification-content js-metrics-agreement">
67+
<h3 class="js-metrics-notification-heading metrics-notification-heading montserrat">
68+
Metrics and Telemetry Notice
69+
</h3>
70+
<!-- metric agreement -->
71+
<span class="metrics-notification-text montserrat">
72+
This site collects metrics and other telemetry data in accordance with our <a href="https://github.com/ipfs-shipyard/ignite-metrics/blob/main/docs/telemetry/COLLECTION_POLICY.md">metrics collection policy</a>. You can learn more about
73+
how we use this information and customize your preferences by clicking “manage settings” below.
6874
</span>
6975
<div class="metrics-notification-buttons">
70-
<button id="metrics-notification-warning-close" class="js-metrics-notification-warning-close">✕&nbsp;Close</button>
76+
<button id="metrics-notification-manage" class="js-metrics-notification-manage">Manage settings</button>
77+
<button id="metrics-notification-confirm" class="primary js-metrics-notification-confirm">Got it!</button>
7178
</div>
7279
</div>
73-
</div>
74-
<div class="hidden js-metrics-notification metrics-notification-wrapper bg-navy bt bw1 border-aqua">
75-
<div class="metrics-notification-spacer"></div>
76-
<div class="metrics-notification-container">
77-
<span class="metrics-notification-text">We're collecting <a href="https://github.com/ipfs/ipfs-gui/issues/125">web-vitals, pageview, and other metrics</a> in order to improve and prioritize our work on IPFS and its public gateways.
78-
Please consent to the collection of these metrics to assist in our efforts!</span>
80+
<div class="hidden metrics-notification-content metrics-notification-content-preferences js-metrics-preferences">
81+
<h3 class="js-metrics-notification-heading metrics-notification-heading montserrat">
82+
Metrics and Telemetry Settings
83+
</h3>
84+
<!-- manage preferences -->
85+
<span class="metrics-notification-text montserrat">
86+
This site collects metrics and other telemetry data in order to improve and prioritize work on IPFS. It does not collect any personally identifiable information.
87+
</span>
88+
<div class="metrics-notification-customize">
89+
<span class="metrics-notification-text metrics-notification-customize-text montserrat">
90+
Opt-in or out at any time by using the toggle below.
91+
For more details, read the full <a href="https://github.com/ipfs-shipyard/ignite-metrics/blob/main/docs/telemetry/COLLECTION_POLICY.md">metrics collection policy</a>.
92+
</span>
93+
<ul class="metrics-notification-preference-list">
94+
<li class="metrics-notification-preference-list-item">
95+
<span class="preference-list-item-text">Minimal Telemetry</span>
96+
<label class="preference-list-item-switch">
97+
<input class="js-necessary-toggle" type="checkbox">
98+
<span class="toggle-slider"></span>
99+
</label>
100+
</li>
101+
</ul>
102+
</div>
79103
<div class="metrics-notification-buttons">
80-
<button id="metrics-notification-accept" class="js-metrics-notification-accept">Allow</button>
81-
<button id="metrics-notification-decline" class="js-metrics-notification-decline">Decline</button>
104+
<button id="metrics-notification-preferences-save" class="primary js-metrics-notification-preferences-save">
105+
Save and Exit
106+
</button>
82107
</div>
83108
</div>
84109
</div>
85-
<button class="cookieConsentToggle js-cookie-banner-toggle" aria-label="Edit cookie settings">
86-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
87-
<path d="M510.52 255.82c-69.97-.85-126.47-57.69-126.47-127.86-70.17
88-
0-127-56.49-127.86-126.45-27.26-4.14-55.13.3-79.72 12.82l-69.13
89-
35.22a132.221 132.221 0 0 0-57.79 57.81l-35.1 68.88a132.645 132.645 0 0
90-
0-12.82 80.95l12.08 76.27a132.521 132.521 0 0 0 37.16 72.96l54.77
91-
54.76a132.036 132.036 0 0 0 72.71 37.06l76.71 12.15c27.51 4.36 55.7-.11
92-
80.53-12.76l69.13-35.21a132.273 132.273 0 0 0
93-
57.79-57.81l35.1-68.88c12.56-24.64 17.01-52.58 12.91-79.91zM176
94-
368c-17.67 0-32-14.33-32-32s14.33-32 32-32 32 14.33 32 32-14.33 32-32
95-
32zm32-160c-17.67 0-32-14.33-32-32s14.33-32 32-32 32 14.33 32 32-14.33
96-
32-32 32zm160 128c-17.67 0-32-14.33-32-32s14.33-32 32-32 32 14.33 32
97-
32-14.33 32-32 32z" />
110+
111+
<button class="metricsConsentToggle js-metrics-modal-toggle" aria-label="Edit metrics settings">
112+
<svg width="43" height="43" viewBox="0 0 43 43" fill="none" xmlns="http://www.w3.org/2000/svg">
113+
<circle cx="21.2333" cy="21.4634" r="20.3114" fill="white" stroke="white" />
114+
<rect x="8.35547" y="17.8948" width="6.0781" height="14.5421" fill="#C4C7D6" />
115+
<rect x="18.4336" y="21.7493" width="6.0781" height="10.6877" fill="#C4C7D6" />
116+
<rect x="28.5117" y="15.4712" width="6.0781" height="16.9658" fill="#C4C7D6" />
117+
<circle cx="10.5458" cy="14.0489" r="1.21184" fill="#C4C7D6" />
118+
<circle cx="21.4716" cy="18.2176" r="1.21184" fill="#C4C7D6" />
119+
<circle cx="31.9208" cy="10.5678" r="1.21184" fill="#C4C7D6" />
120+
<path d="M10.5352 14.0284L21.5802 18.3007L32.104 10.6941" stroke="#C4C7D6" />
98121
</svg>
99122
</button>
100123
</div>

src/metrics.ts

Lines changed: 72 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,71 +2,82 @@ import Countly from 'countly-sdk-web'
22

33
const metricsConsent = localStorage.getItem('metrics_consent')
44

5-
const banner = document.querySelector('.js-metrics-notification')
6-
const declineWarning = document.querySelector('.js-metrics-notification-decline-warning')
7-
const acceptButton = document.querySelector('.js-metrics-notification-accept')
8-
const declineButton = document.querySelector('.js-metrics-notification-decline')
9-
const declineWarningClose = document.querySelector('.js-metrics-notification-warning-close')
10-
const bannerToggle = document.querySelector('.js-cookie-banner-toggle')
5+
const metricsNotificationModal = document.querySelector('.js-metrics-notification-modal')
6+
const metricsAgreementContent = document.querySelector('.js-metrics-agreement')
7+
const metricsManagePreferencesContent = document.querySelector('.js-metrics-preferences')
8+
9+
const closeNotificationModalX = document.querySelector('.js-modal-close')
10+
const confirmMetricNoticeBtn = document.querySelector('.js-metrics-notification-confirm')
11+
12+
const saveMetricPreferencesBtn = document.querySelector('.js-metrics-notification-preferences-save')
13+
14+
const managePreferencesBtn = document.querySelector('.js-metrics-notification-manage')
15+
const necessaryMetricsToggle = document.querySelector('.js-necessary-toggle') as HTMLInputElement
16+
const metricsModalToggle = document.querySelector('.js-metrics-modal-toggle')
1117

1218
function addConsent (consent: string[]): void {
13-
hideConsentBanner()
1419
Countly.add_consent(consent)
1520

1621
if (Array.isArray(consent)) {
1722
localStorage.setItem('metrics_consent', JSON.stringify(consent))
1823
} else {
19-
localStorage.setItem('metrics_consent', JSON.stringify([consent]))
24+
localStorage.setItem(
25+
'metrics_consent',
26+
JSON.stringify([consent])
27+
)
2028
}
2129
}
2230

2331
function addConsentEventHandler (): void {
24-
acceptButton?.removeEventListener('click', addConsentEventHandler)
32+
metricsNotificationModal?.classList.add('hidden')
2533

26-
addConsent(['all'])
34+
addConsent(['minimal'])
2735
}
2836

29-
function declineConsentEventHandler (): void {
30-
addConsent(['necessary'])
31-
hideConsentBanner()
32-
displayDeclineWarning()
33-
}
37+
function updateNecessaryMetricPreferences (): void {
38+
const necessaryMetricsAccepted = necessaryMetricsToggle.checked
3439

35-
function displayDeclineWarning (): void {
36-
declineWarning?.classList.remove('hidden')
37-
bannerToggle?.setAttribute('disabled', '')
40+
if (necessaryMetricsAccepted) {
41+
addConsent(['minimal'])
42+
} else {
43+
Countly.remove_consent(['minimal'])
44+
localStorage.setItem('metrics_consent', JSON.stringify([]))
45+
}
3846
}
3947

40-
function declineWarningCloseEventHandler (): void {
41-
declineWarningClose?.removeEventListener('click', declineWarningCloseEventHandler)
42-
declineWarning?.classList.add('hidden')
43-
bannerToggle?.removeAttribute('disabled')
48+
function initMetricsModal (): void {
49+
metricsNotificationModal?.classList.remove('hidden')
50+
confirmMetricNoticeBtn?.classList.remove('hidden')
51+
managePreferencesBtn?.classList.remove('hidden')
52+
metricsAgreementContent?.classList.remove('hidden')
53+
closeNotificationModalX?.addEventListener('click', hideMetricsModal)
54+
confirmMetricNoticeBtn?.addEventListener('click', addConsentEventHandler)
55+
managePreferencesBtn?.addEventListener('click', managePreferencesClicked)
4456
}
4557

46-
function hideConsentBanner (): void {
47-
acceptButton?.removeEventListener('click', addConsentEventHandler)
48-
declineButton?.removeEventListener('click', declineConsentEventHandler)
49-
banner?.classList.add('hidden')
50-
bannerToggle?.removeAttribute('disabled')
58+
function hideMetricsModal (): void {
59+
metricsNotificationModal?.classList.add('hidden')
60+
metricsManagePreferencesContent?.classList.add('hidden')
61+
metricsAgreementContent?.classList.remove('hidden')
5162
}
5263

53-
/**
54-
* Display the consent banner and handle the user's choice
55-
*/
56-
function displayConsentBanner (): void {
57-
acceptButton?.addEventListener('click', addConsentEventHandler)
58-
declineButton?.addEventListener('click', declineConsentEventHandler)
59-
declineWarningClose?.addEventListener('click', declineWarningCloseEventHandler)
60-
banner?.classList.remove('hidden')
61-
bannerToggle?.setAttribute('disabled', '')
62-
declineWarning?.classList.add('hidden')
64+
function managePreferencesClicked (): void {
65+
const metricsConsent = localStorage.getItem('metrics_consent')
66+
if (metricsConsent != null) necessaryMetricsToggle.checked = JSON.parse(metricsConsent)[0] === 'minimal'
67+
metricsAgreementContent?.classList.add('hidden')
68+
saveMetricPreferencesBtn?.classList.remove('hidden')
69+
metricsManagePreferencesContent?.classList.remove('hidden')
70+
71+
necessaryMetricsToggle.addEventListener('click', updateNecessaryMetricPreferences)
72+
saveMetricPreferencesBtn?.addEventListener('click', hideMetricsModal)
6373
}
6474

65-
function bannerToggleEventHandler (): void {
66-
displayConsentBanner()
75+
function metricsModalToggleEventHandler (): void {
76+
initMetricsModal()
6777
}
78+
6879
function loadCountly (): void {
69-
bannerToggle?.addEventListener('click', bannerToggleEventHandler)
80+
metricsModalToggle?.addEventListener('click', metricsModalToggleEventHandler)
7081
Countly.init({
7182
app_key: '3c2c0819434074fc4d339ddd8e112a1e741ecb72',
7283
url: 'https://countly.ipfs.io',
@@ -75,17 +86,26 @@ function loadCountly (): void {
7586
/**
7687
* @see https://support.count.ly/hc/en-us/articles/360037441932-Web-analytics-JavaScript-#features-for-consent
7788
*/
78-
const necessaryFeatures = ['sessions', 'views']
79-
const marketingFeatures = ['attribution', 'users', 'location']
80-
const performanceFeatures = ['events', 'crashes', 'apm']
81-
const trackingFeatures = ['scrolls', 'clicks', 'forms', 'star-rating', 'feedback']
89+
90+
const minimalFeatures = ['sessions', 'views', 'events']
91+
const performanceFeatures = ['crashes', 'apm']
92+
const uxFeatures = ['scrolls', 'clicks', 'forms']
93+
const feedbackFeatures = ['star-rating', 'feedback']
94+
const locationFeatures = ['location']
8295

8396
Countly.group_features({
84-
all: [...necessaryFeatures, ...marketingFeatures, ...performanceFeatures, ...trackingFeatures],
85-
necessary: necessaryFeatures,
86-
marketing: marketingFeatures,
87-
tracking: trackingFeatures,
88-
performance: performanceFeatures
97+
all: [
98+
...minimalFeatures,
99+
...performanceFeatures,
100+
...uxFeatures,
101+
...feedbackFeatures,
102+
...locationFeatures
103+
],
104+
minimal: minimalFeatures,
105+
performance: performanceFeatures,
106+
ux: uxFeatures,
107+
feedback: feedbackFeatures,
108+
location: locationFeatures
89109
})
90110

91111
/**
@@ -102,17 +122,10 @@ function loadCountly (): void {
102122
Countly.track_view()
103123

104124
if (metricsConsent != null) {
105-
try {
106-
addConsent(JSON.parse(metricsConsent))
107-
} catch {
108-
displayConsentBanner()
109-
}
125+
addConsent(JSON.parse(metricsConsent))
110126
} else {
111-
displayConsentBanner()
127+
addConsent(['minimal'])
112128
}
113129
}
114130

115-
export {
116-
loadCountly,
117-
Countly
118-
}
131+
export { loadCountly, Countly }

0 commit comments

Comments
 (0)