@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 CHANGED
@@ -1,5 +1,5 @@
1
1
  The MIT License (MIT)
2
- Copyright (c) 2022 Jari Jokinen
2
+ Copyright (c) 2022 - 2025 Jari Jokinen
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy of
5
5
  this software and associated documentation files (the "Software"), to deal in
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # consent
2
2
 
3
- A zero-dependency, vanilla JavaScript consent manager with native Consent Mode
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
- Yarn:
12
+ ## Usage
13
13
 
14
- yarn add @jarijokinen/consent
14
+ Load the consent-loader.js in the HEAD section deferred before any GTM tags.
15
15
 
16
- ## Usage
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
- Initialization:
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-link">Cookie Settings</a>
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
- settingsLinkSelector: '.consent-settings-link'
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). See
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.3",
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
- denyAll: 'Deny All',
8
+ allowAll: 'Allow All',
9
9
  allowSelected: 'Allow Selected',
10
- allowAll: 'Allow All'
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
- settingsLinkSelector: '.consent-settings-link',
19
+ dialogTitle: 'Cookie Consent',
20
+ dialogMessage: 'This website uses cookies for:',
21
+ settingsLinkSelector: '.consent-settings',
22
22
  ...options
23
23
  };
24
-
25
- let consentState = {
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 (getConsent(storage) === 'granted') {
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((storage) => {
101
- consentState[storage] = 'denied';
60
+ Object.keys(opts.storages).forEach(k => {
61
+ window.consent.state[k] = 'denied'
102
62
  });
103
- updateConsent();
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((storage) => {
111
- consentState[storage] = document.querySelector(
112
- '#consent-field-' + storage
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
- updateConsent();
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((storage) => {
125
- consentState[storage] = 'granted';
81
+ Object.keys(opts.storages).forEach(k => {
82
+ window.consent.state[k] = 'granted';
126
83
  });
127
- updateConsent();
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
  };