@jarijokinen/consent 0.0.3 → 0.0.5
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.
- package/LICENSE.txt +1 -1
- package/README.md +17 -12
- package/package.json +6 -3
- package/src/consent-loader.js +39 -0
- package/src/consent.js +46 -63
package/LICENSE.txt
CHANGED
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# consent
|
|
2
2
|
|
|
3
|
-
A zero-dependency, vanilla JavaScript consent manager with native
|
|
4
|
-
support.
|
|
3
|
+
A zero-dependency, vanilla JavaScript consent manager with native Google
|
|
4
|
+
Consent Mode v2 support.
|
|
5
5
|
|
|
6
6
|
## Installation
|
|
7
7
|
|
|
@@ -9,13 +9,18 @@ NPM:
|
|
|
9
9
|
|
|
10
10
|
npm install @jarijokinen/consent
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
## Usage
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Load the consent-loader.js in the HEAD section deferred before any GTM tags.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
<head>
|
|
17
|
+
<script src="path/to/consent-loader.js" defer></script>
|
|
18
|
+
<script>
|
|
19
|
+
// GTM and any other scripts
|
|
20
|
+
</script>
|
|
21
|
+
</head>
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
Import consent from the npm package and initialize it later on the page.
|
|
19
24
|
|
|
20
25
|
import { consent } from '@jarijokinen/consent';
|
|
21
26
|
|
|
@@ -25,7 +30,7 @@ Initialization:
|
|
|
25
30
|
|
|
26
31
|
Add link that opens the dialog:
|
|
27
32
|
|
|
28
|
-
<a href="#" class="consent-settings
|
|
33
|
+
<a href="#" class="consent-settings">Cookie Settings</a>
|
|
29
34
|
|
|
30
35
|
## Configuration
|
|
31
36
|
|
|
@@ -48,16 +53,16 @@ argument to the consent() function.
|
|
|
48
53
|
<div class="consent-fields"></div>
|
|
49
54
|
<div class="consent-buttons"></div>
|
|
50
55
|
`,
|
|
51
|
-
dialogTitle: 'Cookies',
|
|
52
|
-
dialogMessage: 'We would like to get your permission to use cookies for:',
|
|
53
56
|
dialogClass: 'consent',
|
|
54
|
-
|
|
57
|
+
dialogTitle: 'Cookie Consent',
|
|
58
|
+
dialogMessage: 'This website uses cookies for:',
|
|
59
|
+
settingsLinkSelector: '.consent-settings'
|
|
55
60
|
};
|
|
56
61
|
|
|
57
62
|
consent(options);
|
|
58
63
|
|
|
59
64
|
## License
|
|
60
65
|
|
|
61
|
-
MIT License. Copyright (c) 2022 [Jari Jokinen](https://jarijokinen.com).
|
|
62
|
-
[LICENSE](https://github.com/jarijokinen/consent/blob/main/LICENSE.txt)
|
|
66
|
+
MIT License. Copyright (c) 2022 - 2025 [Jari Jokinen](https://jarijokinen.com).
|
|
67
|
+
See [LICENSE](https://github.com/jarijokinen/consent/blob/main/LICENSE.txt)
|
|
63
68
|
for further details.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarijokinen/consent",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "A zero-dependency, vanilla JavaScript consent manager with native Consent Mode support.",
|
|
3
|
+
"version": "0.0.5",
|
|
4
|
+
"description": "A zero-dependency, vanilla JavaScript consent manager with native Google Consent Mode v2 support.",
|
|
5
5
|
"main": "src/consent.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -12,5 +12,8 @@
|
|
|
12
12
|
"bugs": {
|
|
13
13
|
"url": "https://github.com/jarijokinen/consent/issues"
|
|
14
14
|
},
|
|
15
|
-
"homepage": "https://github.com/jarijokinen/consent#readme"
|
|
15
|
+
"homepage": "https://github.com/jarijokinen/consent#readme",
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
}
|
|
16
19
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
window.dataLayer = window.dataLayer || [];
|
|
2
|
+
function gtag() { dataLayer.push(arguments); }
|
|
3
|
+
|
|
4
|
+
window.consent = window.consent || {};
|
|
5
|
+
window.consent.countries = window.consent.countries || [
|
|
6
|
+
'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU',
|
|
7
|
+
'IS', 'IE', 'IT', 'LV', 'LI', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO',
|
|
8
|
+
'SK', 'SI', 'ES', 'SE', 'UK', 'GB', 'CH'
|
|
9
|
+
];
|
|
10
|
+
window.consent.consentMissing = true
|
|
11
|
+
window.consent.state = {
|
|
12
|
+
analytics_storage: null,
|
|
13
|
+
ad_storage: null,
|
|
14
|
+
ad_user_data: null,
|
|
15
|
+
ad_personalization: null
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
Object.keys(window.consent.state).forEach(k => {
|
|
19
|
+
try {
|
|
20
|
+
const v = localStorage.getItem('consent_' + k);
|
|
21
|
+
if (v === 'granted' || v === 'denied') {
|
|
22
|
+
window.consent.state[k] = v;
|
|
23
|
+
window.consent.consentMissing = false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
window.consent.state[k] = null;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const country = document.cookie.split(/(?:^|;\s*)cc=/).pop().split(';')[0]
|
|
32
|
+
.trim().toUpperCase();
|
|
33
|
+
const countryDefault = !country || window.consent.countries.includes(country)
|
|
34
|
+
? 'denied' : 'granted';
|
|
35
|
+
|
|
36
|
+
gtag('consent', 'default', {
|
|
37
|
+
...Object.fromEntries(Object.entries(window.consent.state).map(([k, v]) =>
|
|
38
|
+
[k, v ?? countryDefault]))
|
|
39
|
+
});
|
package/src/consent.js
CHANGED
|
@@ -5,9 +5,9 @@ export const consent = (options) => {
|
|
|
5
5
|
ad_storage: 'Marketing'
|
|
6
6
|
},
|
|
7
7
|
actions: {
|
|
8
|
-
|
|
8
|
+
allowAll: 'Allow All',
|
|
9
9
|
allowSelected: 'Allow Selected',
|
|
10
|
-
|
|
10
|
+
denyAll: 'Deny All'
|
|
11
11
|
},
|
|
12
12
|
dialogMarkup: `
|
|
13
13
|
<h2 class="consent-title"></h2>
|
|
@@ -15,58 +15,18 @@ export const consent = (options) => {
|
|
|
15
15
|
<div class="consent-fields"></div>
|
|
16
16
|
<div class="consent-buttons"></div>
|
|
17
17
|
`,
|
|
18
|
-
dialogTitle: 'Cookies',
|
|
19
|
-
dialogMessage: 'We would like to get your permission to use cookies for:',
|
|
20
18
|
dialogClass: 'consent',
|
|
21
|
-
|
|
19
|
+
dialogTitle: 'Cookie Consent',
|
|
20
|
+
dialogMessage: 'This website uses cookies for:',
|
|
21
|
+
settingsLinkSelector: '.consent-settings',
|
|
22
22
|
...options
|
|
23
23
|
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
ad_storage: 'denied',
|
|
27
|
-
analytics_storage: 'denied',
|
|
28
|
-
functionality_storage: 'denied',
|
|
29
|
-
personalization_storage: 'denied',
|
|
30
|
-
security_storage: 'denied'
|
|
31
|
-
};
|
|
24
|
+
|
|
25
|
+
function gtag() { dataLayer.push(arguments); }
|
|
32
26
|
|
|
33
27
|
let dialog = document.createElement('div');
|
|
34
28
|
dialog.classList.add(opts.dialogClass);
|
|
35
29
|
|
|
36
|
-
const getConsent = (storage) => {
|
|
37
|
-
return localStorage.getItem('consent_' + storage);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const updateConsent = () => {
|
|
41
|
-
Object.keys(opts.storages).forEach((storage) => {
|
|
42
|
-
localStorage.setItem('consent_' + storage, consentState[storage]);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
if (typeof gtag === 'function') {
|
|
46
|
-
gtag('consent', 'update', consentState);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const updateFields = () => {
|
|
51
|
-
Object.keys(opts.storages).forEach((storage) => {
|
|
52
|
-
dialog.querySelector('#consent-field-' + storage).checked =
|
|
53
|
-
consentState[storage] == 'granted' ? true : false;
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const loadConsentState = () => {
|
|
58
|
-
Object.keys(opts.storages).forEach((storage) => {
|
|
59
|
-
consentState[storage] = getConsent(storage);
|
|
60
|
-
if (consentState[storage] === null) {
|
|
61
|
-
showDialog();
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
if (typeof gtag === 'function') {
|
|
66
|
-
gtag('consent', 'update', consentState);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
30
|
const createDialog = () => {
|
|
71
31
|
dialog.innerHTML = opts.dialogMarkup;
|
|
72
32
|
dialog.querySelector('.consent-title').innerText = opts.dialogTitle;
|
|
@@ -78,7 +38,7 @@ export const consent = (options) => {
|
|
|
78
38
|
checkbox.setAttribute('type', 'checkbox');
|
|
79
39
|
checkbox.setAttribute('name', 'consent-field-' + storage);
|
|
80
40
|
checkbox.setAttribute('id', 'consent-field-' + storage);
|
|
81
|
-
if (
|
|
41
|
+
if (window.consent.state[storage] === 'granted') {
|
|
82
42
|
checkbox.setAttribute('checked', 'checked');
|
|
83
43
|
}
|
|
84
44
|
const label = document.createElement('label');
|
|
@@ -97,34 +57,31 @@ export const consent = (options) => {
|
|
|
97
57
|
switch (action) {
|
|
98
58
|
case 'denyAll':
|
|
99
59
|
button.onclick = () => {
|
|
100
|
-
Object.keys(opts.storages).forEach(
|
|
101
|
-
|
|
60
|
+
Object.keys(opts.storages).forEach(k => {
|
|
61
|
+
window.consent.state[k] = 'denied'
|
|
102
62
|
});
|
|
103
|
-
|
|
63
|
+
saveState();
|
|
104
64
|
updateFields();
|
|
105
65
|
hideDialog();
|
|
106
66
|
};
|
|
107
67
|
break;
|
|
108
68
|
case 'allowSelected':
|
|
109
69
|
button.onclick = () => {
|
|
110
|
-
Object.keys(opts.storages).forEach(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
).checked
|
|
114
|
-
? 'granted'
|
|
115
|
-
: 'denied';
|
|
70
|
+
Object.keys(opts.storages).forEach(k => {
|
|
71
|
+
const el = document.querySelector('#consent-field-' + k);
|
|
72
|
+
window.consent.state[k] = el.checked ? 'granted' : 'denied';
|
|
116
73
|
});
|
|
117
|
-
|
|
74
|
+
saveState();
|
|
118
75
|
updateFields();
|
|
119
76
|
hideDialog();
|
|
120
77
|
};
|
|
121
78
|
break;
|
|
122
79
|
case 'allowAll':
|
|
123
80
|
button.onclick = () => {
|
|
124
|
-
Object.keys(opts.storages).forEach(
|
|
125
|
-
|
|
81
|
+
Object.keys(opts.storages).forEach(k => {
|
|
82
|
+
window.consent.state[k] = 'granted';
|
|
126
83
|
});
|
|
127
|
-
|
|
84
|
+
saveState();
|
|
128
85
|
updateFields();
|
|
129
86
|
hideDialog();
|
|
130
87
|
};
|
|
@@ -137,6 +94,26 @@ export const consent = (options) => {
|
|
|
137
94
|
document.querySelector('body').appendChild(dialog);
|
|
138
95
|
};
|
|
139
96
|
|
|
97
|
+
const saveState = () => {
|
|
98
|
+
Object.keys(window.consent.state).forEach(k => {
|
|
99
|
+
try {
|
|
100
|
+
localStorage.setItem('consent_' + k, window.consent.state[k]);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
console.log('Unable to save consent to local storage');
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
gtag('consent', 'update', window.consent.state);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const updateFields = () => {
|
|
111
|
+
Object.keys(opts.storages).forEach(k => {
|
|
112
|
+
dialog.querySelector('#consent-field-' + k).checked =
|
|
113
|
+
window.consent.state[k] === 'granted' ? true : false;
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
140
117
|
const showDialog = () => {
|
|
141
118
|
dialog.style.display = 'block';
|
|
142
119
|
};
|
|
@@ -144,12 +121,18 @@ export const consent = (options) => {
|
|
|
144
121
|
const hideDialog = () => {
|
|
145
122
|
dialog.style.display = 'none';
|
|
146
123
|
};
|
|
147
|
-
|
|
124
|
+
|
|
148
125
|
document.querySelector(opts.settingsLinkSelector).onclick = (ev) => {
|
|
149
126
|
ev.preventDefault();
|
|
150
127
|
showDialog();
|
|
151
128
|
};
|
|
152
129
|
|
|
153
|
-
loadConsentState();
|
|
154
130
|
createDialog();
|
|
131
|
+
|
|
132
|
+
if (window.consent.consentMissing) {
|
|
133
|
+
showDialog();
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
hideDialog();
|
|
137
|
+
}
|
|
155
138
|
};
|