chefcookie 2.3.3 → 2.3.4

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/README.md CHANGED
@@ -1,486 +1,488 @@
1
- # 👻 chefcookie 👻
2
-
3
- chefcookie is a gdpr cookie solution without compromises.
4
-
5
- ## features
6
-
7
- - opt in/out
8
- - highly customizable
9
- - custom event tracking
10
- - duration tracking
11
- - scroll depth tracking
12
- - includes basic styling
13
- - multi language support
14
- - ships multiple layouts (overlay, bottombar, topbar)
15
- - supports custom tracking scripts
16
- - auto disable tracking for logged in wordpress users
17
- - ie11 support available
18
- - script grouping with optional optin on script level
19
-
20
- ## included
21
-
22
- - [google analytics](https://analytics.google.com)
23
- - [google tag manager](https://tagmanager.google.com)
24
- - [facebook ads](https://de-de.facebook.com/business/products/ads)
25
- - [twitter ads](https://ads.twitter.com)
26
- - [taboola ads](https://www.taboola.com)
27
- - [match2one ads](https://www.match2one.com)
28
- - [linkedin](https://business.linkedin.com/marketing-solutions/conversion-tracking)
29
- - [etracker](https://www.etracker.com)
30
- - [matomo analytics](https://matomo.org)
31
- - [smartlook](https://www.smartlook.com)
32
- - [crazy egg](https://www.crazyegg.com)
33
- - [google maps](https://developers.google.com/maps/documentation/javascript/tutorial)
34
-
35
- ## installation
36
-
37
- use it as a module:
38
-
39
- ```
40
- npm install chefcookie
41
- ```
42
-
43
- ```js
44
- import chefcookie from 'chefcookie';
45
- ```
46
-
47
- or include it the traditional way:
48
-
49
- ```html
50
- <script src="chefcookie.min.js"></script>
51
- ```
52
-
53
- ## usage
54
-
55
- ```js
56
- const cc = new chefcookie({
57
- message: {
58
- de: `
59
- <h2>Wir verwenden Cookies</h2>
60
- <p>
61
- Unsere Website verwendet Cookies, die uns helfen, unsere Website zu verbessern, den bestmöglichen Service zu bieten und ein optimales Kundenerlebnis zu ermöglichen. <a href="#chefcookie__settings">Hier</a> können Sie Ihre Einstellungen verwalten. Indem Sie auf "<a href="#chefcookie__accept">Akzeptieren</a>" klicken, erklären Sie sich damit einverstanden, dass Ihre Cookies für diesen Zweck verwendet werden. Weitere Informationen dazu finden Sie in unserer <a href="/de/datenschutz">Datenschutzerklärung</a> sowie im <a href="/de/impressum">Impressum</a>. Sollten Sie hiermit nicht einverstanden sein, können Sie die Verwendung von Cookies hier <a href="#chefcookie__decline">ablehnen</a>.
62
- </p>
63
- `,
64
- en: `
65
- <h2>We use cookies</h2>
66
- <p>
67
- Our website uses cookies that help us to improve our website, provide the best possible service and enable an optimal customer experience. <a href="#chefcookie__settings">Here</a> you can manage your settings. By clicking on "<a href="#chefcookie__accept">Accept</a>", you agree that your cookies may be used for this purpose. You can find further information on this in our <a href="/en/privacy">data protection declaration</a> and in the <a href="/en/imprint">imprint</a>. If you do not agree to this, you can refuse the use of cookies here <a href="#chefcookie__decline">reject</a> the use of cookies.
68
- </p>
69
- `
70
- },
71
- accept_all_if_settings_closed: true,
72
- show_decline_button: false,
73
- scripts_selection: 'collapse', // false|true|'collapse'
74
- debug_log: false,
75
- consent_tracking: null, // '/wp-json/v1/track-consent.php'
76
- expiration: 7, // in days
77
- exclude_google_pagespeed: true,
78
- style: {
79
- layout: 'overlay', // overlay|bottombar|topbar
80
- size: 3, // 1|2|3|4|5
81
- color_text: '#595f60',
82
- color_highlight: '#ff0000',
83
- color_background: '#eeeeee',
84
- highlight_accept: true,
85
- show_disabled_checkbox: true,
86
- noscroll: true,
87
- fade: true,
88
- blur: true
89
- },
90
- labels: {
91
- accept: { de: 'Akzeptieren', en: 'Accept' },
92
- accept_all: { de: 'Alles akzeptieren', en: 'Accept all' },
93
- settings_open: { de: 'Einstellungen festlegen', en: 'Change settings' },
94
- settings_close: { de: 'Einstellungen schliessen', en: 'Close settings' },
95
- group_open: { de: 'Weitere Informationen anzeigen', en: 'Show more information' },
96
- group_close: { de: 'Weitere Informationen schliessen', en: 'Close more information' },
97
- decline: { de: 'Nur erforderliche Cookies', en: 'Only necessary cookies' },
98
- details_open: { de: 'Details anzeigen', en: 'Show details' },
99
- details_close: { de: 'Details schliessen', en: 'Close details' }
100
- },
101
- exclude: [
102
- // exclude privacy site if needed
103
- '/de/datenschutz',
104
- '/en/privacy',
105
- '/de/impressum',
106
- '/en/imprint',
107
- // exclude wordpress users
108
- () => {
109
- return document.cookie !== undefined && document.cookie.indexOf('wp-settings-time') > -1;
110
- }
111
- ],
112
- settings: [
113
- {
114
- title: { de: 'Analysen', en: 'Analyses' },
115
- description: {
116
- de: 'Tools, die anonyme Daten über Website-Nutzung und -Funktionalität sammeln. Wir nutzen die Erkenntnisse, um unsere Produkte, Dienstleistungen und das Benutzererlebnis zu verbessern.',
117
- en: 'Tools that collect anonymous data about website usage and functionality. We use this information to improve our products, services and user experience.'
118
- },
119
- checked_by_default: true,
120
- cannot_be_modified: false,
121
- initial_tracking: false,
122
- scripts: {
123
- analytics: 'UA-xxxxxxxx-1',
124
- // extended syntax
125
- analytics: {
126
- id: 'UA-xxxxxxxx-1',
127
- title: { de: 'Google Analytics', en: 'Google Analytics' },
128
- description: {
129
- de: 'Die Verwendung der Analyse Cookies erfolgt zu dem Zweck, die Qualität unserer Website und ihre Inhalte zu verbessern und die Funktionsfähigkeit von eingebundenen Diensten unserer Partner sicherzustellen.',
130
- en: `
131
- <p>
132
- Google Analytics cookies are used to improve the quality of our website and its content and to ensure the functionality of integrated services of our partners.
133
- </p>
134
- <table>
135
- <tr><td>Name:</td><td>_gid</td></tr>
136
- <tr><td>Host:</td><td>www.tld.com</td></tr>
137
- <tr><td>Duration:</td><td>Session</td></tr>
138
- <tr><td>Type:</td><td>1st Party</td></tr>
139
- <tr><td>Description:</td><td>This is a pattern type cookie name associated with a marketing cloud. It stores an unique visitor identifier, and uses an organisation identifier.</td></tr>
140
- </table>
141
- `
142
- }
143
- }
144
- }
145
- },
146
- {
147
- title: { de: 'Werbung', en: 'Advertising' },
148
- description: {
149
- de: 'Anonyme Informationen, die wir sammeln, um Ihnen nützliche Produkte und Dienstleistungen empfehlen zu können.',
150
- en: 'Anonymous information that we collect in order to recommend useful products and services to you.'
151
- },
152
- checked_by_default: true,
153
- cannot_be_modified: false,
154
- initial_tracking: false,
155
- scripts: {
156
- tagmanager: 'GTM-XXXXXXX',
157
- facebook: 'xxxxxxxxxxxxxxx',
158
- twitter: 'single',
159
- taboola: 'xxxxxxx',
160
- match2one: 'xxxxxxxx',
161
- linkedin: 'xxxxxxx',
162
- etracker: 'xxxxxx',
163
- matomo: 'xxxxxx#x', // domain/siteid
164
- smartlook: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
165
- crazyegg: 'xxxx/xxxx',
166
- google_maps: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
167
- }
168
- },
169
- {
170
- title: { de: 'Drittanbieter', en: 'Third-party' },
171
- description: {
172
- de: 'Tools, die interaktive Services wie beispielsweise Video- und Kartendienste unterstützen.',
173
- en: 'Tools that support interactive services such as video and map services.'
174
- },
175
- checked_by_default: true,
176
- cannot_be_modified: false,
177
- initial_tracking: false,
178
- scripts: {}
179
- },
180
- {
181
- title: { de: 'Grundlegendes', en: 'Basics' },
182
- description: {
183
- de: 'Tools, die wesentliche Services und Funktionen ermöglichen, einschließlich Identitätsprüfung, Servicekontinuität und Standortsicherheit. Diese Option kann nicht abgelehnt werden.',
184
- en: 'Tools that enable essential services and functions, including identity verification, service continuity, and site security. This option cannot be declined.'
185
- },
186
- checked_by_default: true,
187
- cannot_be_modified: true,
188
- initial_tracking: true,
189
- scripts: {
190
- example_script1: {}, // this immediately gets "resolved"
191
- example_script2: {
192
- accept: (cc, resolve, isInit) => {
193
- /* example: load default scripts inside custom script */
194
- cc.load('analytics', 'UA-xxxxxxxx-1');
195
- cc.load('tagmanager', 'GTM-XXXXXXX');
196
- cc.load('facebook', 'xxxxxxxxxxxxxxx');
197
- cc.load('twitter', 'single');
198
- cc.load('taboola', 'xxxxxxx');
199
- cc.load('match2one', 'xxxxxxxx');
200
- cc.load('linkedin', 'xxxxxxx');
201
- cc.load('etracker', 'xxxxxx');
202
- cc.load('matomo', 'xxxxxx#x');
203
- cc.load('smartlook', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
204
- cc.load('crazyegg', 'xxxx/xxxx');
205
- cc.load('google_maps', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
206
-
207
- /* example: load (multiple) custom javascripts */
208
- cc.loadJs([
209
- 'script1.js',
210
- 'script2.js',
211
- 'https://www.googletagmanager.com/gtag/js?id=UA-xxxxxxxx-1'
212
- ]).then(() => {
213
- resolve();
214
- });
215
-
216
- /* example: enable uninitialized iframes */
217
- if (document.querySelector('iframe[alt-src*="google.com/maps"]') !== null) {
218
- document.querySelectorAll('iframe[alt-src*="google.com/maps"]').forEach(el => {
219
- el.setAttribute('src', el.getAttribute('alt-src'));
220
- });
221
- }
222
-
223
- /* example: load scripts manually */
224
- let script1 = document.createElement('script');
225
- script1.setAttribute('src', 'https://www.googletagmanager.com/gtag/js?id=UA-xxxxxxxx-1');
226
- script1.onload = () => {
227
- resolve();
228
- };
229
- document.head.appendChild(script1);
230
-
231
- /* example: load scripts manually */
232
- let script2 = document.createElement('script');
233
- let html = "alert('OK');";
234
- script2.innerHTML = html;
235
- document.head.appendChild(script2);
236
-
237
- /* example: load scripts manually (with custom callback) */
238
- window.captchaCallback = () => {
239
- resolve();
240
- };
241
- cc.loadJs('https://www.google.com/recaptcha/api.js?onload=captchaCallback&amp;render=explicit');
242
-
243
- /*
244
- important: always call resolve to show that the script fully has loaded!
245
- if you don't want the accept logic to be inside this function, only call resolve() and use waitFor outside this function to fire further actions */
246
- resolve();
247
-
248
- /* some other helpers */
249
- cc.url(); // gets the current url
250
- cc.lng(); // gets the current lng
251
- isInit; // true|false (accepted actively through click and not via cookie)
252
- },
253
- exclude: () => {
254
- return document.cookie !== undefined && document.cookie.indexOf('wp-settings-time') > -1;
255
- },
256
- title: { de: '...', en: '...' },
257
- description: { de: '...', en: '...' }
258
- }
259
- }
260
- }
261
- ]
262
- });
263
- document.addEventListener('DOMContentLoaded', () => {
264
- cc.init();
265
- });
266
- ```
267
-
268
- #### multi language support
269
-
270
- instead of plain text you can provide language objects for any label:
271
-
272
- ```js
273
- {
274
- title: 'Werbung';
275
- }
276
- ```
277
-
278
- ```js
279
- {
280
- title: { de: 'Werbung', en: 'Advertising' }
281
- }
282
- ```
283
-
284
- chefcookie will find out the current language and show the appropriate strings.
285
-
286
- #### opt out links
287
-
288
- its recommended to place those kind of links inside your privacy page:
289
-
290
- ```html
291
- <a href="#" data-cc-disable="analytics" data-cc-message="Google Analytics aktivieren">Google Analytics deaktivieren</a>
292
- <a href="#" data-cc-disable="tagmanager" data-cc-message="Google Tag Manager aktivieren"
293
- >Google Tag Manager deaktivieren</a
294
- >
295
- <a href="#" data-cc-disable="facebook" data-cc-message="Facebook Pixel aktivieren">Facebook Pixel deaktivieren</a>
296
- <a href="#" data-cc-disable="twitter" data-cc-message="Twitter Pixel aktivieren">Twitter Pixel deaktivieren</a>
297
- <a href="#" data-cc-disable="taboola" data-cc-message="Taboola Pixel aktivieren">Taboola Pixel deaktivieren</a>
298
- <a href="#" data-cc-disable="match2one" data-cc-message="Match2One Pixel aktivieren">Match2One Pixel deaktivieren</a>
299
- <a href="#" data-cc-disable="linkedin" data-cc-message="LinkedIn Pixel aktivieren">LinkedIn Pixel deaktivieren</a>
300
- <a href="#" data-cc-disable="etracker" data-cc-message="etracker aktivieren">etracker deaktivieren</a>
301
- <a href="#" data-cc-disable="matomo" data-cc-message="Matomo aktivieren">Matomo deaktivieren</a>
302
- <a href="#" data-cc-disable="smartlook" data-cc-message="Smartlook aktivieren">Smartlook deaktivieren</a>
303
- <a href="#" data-cc-disable="crazyegg" data-cc-message="Crazy Egg aktivieren">Crazy Egg deaktivieren</a>
304
- <a href="#" data-cc-disable="google_maps" data-cc-message="Google Maps aktivieren">Google Maps deaktivieren</a>
305
- ```
306
-
307
- you can style those links with:
308
-
309
- ```css
310
- [data-cc-disable] {
311
- }
312
- [data-cc-disable].disabled {
313
- }
314
- ```
315
-
316
- #### (one time) opt in links
317
-
318
- these links self destroy if the respective script is accepted:
319
-
320
- ```html
321
- <div data-cc-enable="google_maps">
322
- Ich möchte Google Maps-Inhalte aktivieren und stimme zu, dass Daten von Google geladen werden (siehe
323
- <a href="/de/datenschutz" target="_blank">Datenschutz</a>).
324
- </div>
325
- ```
326
-
327
- it is recommended to place them inside your via js populated divs (like a google maps wrapper).\
328
- if you click on it, the script is explicitly accepted.
329
-
330
- #### manually accept/decline
331
-
332
- ```js
333
- cc.accept('analytics');
334
- cc.decline('analytics');
335
- cc.isAccepted('analytics'); // true|false
336
- ```
337
-
338
- #### backdoor
339
-
340
- just add `?accept=1` to your urls to completely bypass chefcookie.
341
-
342
- #### custom scripts
343
-
344
- the following keywords as keys are reserved:
345
-
346
- - `analytics`
347
- - `tagmanager`
348
- - `facebook`
349
- - `twitter`
350
- - `taboola`
351
- - `match2one`
352
- - `linkedin`
353
- - `etracker`
354
- - `matomo`
355
- - `smartlook`
356
- - `crazyegg`
357
- - `google_maps`
358
-
359
- if you provide strings as values, chefcookie interprets them appropriately. chefcookie then loads the libraries with reasonable default settings. however, you can execute your own functions in either overwriting the values of these reserved keywords (and provide an object) or use any other keyword.
360
-
361
- #### script blocking
362
-
363
- the best strategy is to add no scripts at all and let chefcookie add the scripts later.
364
-
365
- if you cannot do that (e.g. when you cannot manipulate the page content), there are a lot of techniques and strategies out there to prevent existing scripts from executing:
366
-
367
- - use http content-security-policy headers
368
- - manipulate embeds (set `type="javascript/blocked"` or `alt-src="..."`)
369
- - monkey patch `document.createElement`
370
- - watch and modify with `MutationObserver`
371
- - abuse `document.write`
372
-
373
- chefcookie is flexible and very well works together with e.g. [yett](https://github.com/snipsco/yett):
374
-
375
- - init `yett` before chefcookie to block scripts
376
- - call `unblock()` inside chefcookies custom scripts
377
-
378
- #### dynamically load a script
379
-
380
- chefcookie provides a `load`-helper, where you can provide one or multiple urls to load:
381
-
382
- ```js
383
- cc.loadJs(['script1.js', 'script2.js']);
384
- ```
385
-
386
- in order to call `resolve()` (see below), you can use:
387
-
388
- ```js
389
- cc.loadJs(['script1.js', 'script2.js']).then(() => { resolve(); };
390
- cc.loadJs(['script1.js', 'script2.js'], () => { resolve(); }); // also supported
391
- ```
392
-
393
- #### wait for a tracker
394
-
395
- if your javascript is dependent on a specific script loaded by chefcookie, you should handle that case and wait for the tracker being executed:
396
-
397
- ```js
398
- cc.waitFor('google_recaptcha').then(() => {});
399
- cc.waitFor('google_recaptcha', () => {}); // also supported
400
- ```
401
-
402
- this only gets executed when you call `resolve()` inside your custom tracking function.
403
-
404
- #### more
405
-
406
- the cookie banner is shown always, if no consent is saved.\
407
- if done so, it is shown again, after the cookie expired (see the `expiration`-setting).
408
-
409
- it is recommended to include a (re)opening link in the privacy policy, for example.\
410
- here you can also use the following code:
411
-
412
- ```html
413
- <a href="#" data-cc-open>Consent-Einstellungen bearbeiten</a>
414
- ```
415
-
416
- you can programmatically control chefcookie via javascript:
417
-
418
- - `cc.open()`: open the cookie banner manually
419
- - `cc.isOpen()`: check if cookie banner is opened
420
- - `cc.close()`: close the cookie banner manually
421
- - `cc.destroy()`: destroy the cookie banner and all event listeners
422
- - `cc.updateOptOutOptIn()`: refreshes the state of opt out / opt in buttons
423
-
424
- #### consent manager tracking
425
-
426
- to test the acceptance of the consent manager, it is recommended to use the `consent_tracking`-option. if you specify an url (relative or absolute) there, chefcookie sends a post-request with analysis data for every action that a user performs in the consent manager. these requests have the form:
427
-
428
- ```json
429
- {
430
- "action": "accept_all",
431
- "date": "2021-01-01 10:00:00",
432
- "url": "https://tld.com?foo=bar",
433
- "providers": "analytics,facebook,twitter",
434
- "viewport": "the viewport size of the user device"
435
- }
436
- ```
437
-
438
- `url` as you can see consists of potential get-paramaters (so that you can analyze e.g. google ads campaigns).\
439
- take note that nor ip or user agent are posted, but feel free to catch and store these parts with the help of a php endpoint.
440
-
441
- the `action`-key can have the following values:
442
-
443
- - `open`: the consent manager is shown
444
- - `accept_all`: all providers are accepted
445
- - `accept_partially`: providers are accepted partially
446
- - `decline`: all providers are declined
447
- - `settings_open`: settings are opened
448
- - `settings_close`: settings are closed
449
- - `first_user_interaction`: first mouse/touch/scroll interaction happened
450
-
451
- here it makes sense to temporarily store this data in a database and evaluate it – for example, to measure the discrepancy between the real visitor numbers and the numbers in google analytics or to optimize the appearance of the consent manager (e.g. using the `layout`-option).
452
-
453
- #### event tracking
454
-
455
- chefcookie additionally comes with event tracking for all major analytics platforms.\
456
- you can even use this feature with side loaded scripts.
457
-
458
- ```js
459
- window.addEventListener('load', () => {
460
- // track duration (sends action "xxs" in 30 second intervals)
461
- cc.trackDuration();
462
- // track scroll depth (sends "xx%" in scroll steps 1, 10, 25, 50, 75, 100)
463
- cc.trackScrollDepth();
464
- // custom duration
465
- cc.trackDurationCustom(60, () => {
466
- cc.eventAnalytics('60s');
467
- });
468
- // custom scroll depth
469
- cc.trackScrollDepthCustom(25, () => {
470
- cc.eventAnalytics('25%');
471
- });
472
- // custom tracking
473
- document.querySelector('.conversion').addEventListener('click', e => {
474
- cc.eventAnalytics('custom_category', 'custom_action');
475
- cc.eventAnalytics('custom_action');
476
- cc.eventFacebook('custom_action_name');
477
- cc.eventTwitter('conversion_id');
478
- cc.eventTaboola('custom_event_name');
479
- cc.eventMatch2one('id=xxxxxx&seg=xxxxxx');
480
- cc.eventLinkedin('id', 'conversion_id');
481
- cc.eventEtracker('custom_category', 'custom_action');
482
- cc.eventEtracker('custom_action');
483
- e.preventDefault();
484
- });
485
- });
486
- ```
1
+ # 👻 chefcookie 👻
2
+
3
+ chefcookie is a gdpr cookie solution without compromises.
4
+
5
+ ## features
6
+
7
+ - opt in/out
8
+ - highly customizable
9
+ - custom event tracking
10
+ - duration tracking
11
+ - scroll depth tracking
12
+ - includes basic styling
13
+ - multi language support
14
+ - ships multiple layouts (overlay, bottombar, topbar)
15
+ - supports custom tracking scripts
16
+ - auto disable tracking for logged in wordpress users
17
+ - ie11 support available
18
+ - script grouping with optional optin on script level
19
+
20
+ ## included
21
+
22
+ - [google analytics](https://analytics.google.com)
23
+ - [google tag manager](https://tagmanager.google.com)
24
+ - [facebook ads](https://de-de.facebook.com/business/products/ads)
25
+ - [twitter ads](https://ads.twitter.com)
26
+ - [taboola ads](https://www.taboola.com)
27
+ - [match2one ads](https://www.match2one.com)
28
+ - [linkedin](https://business.linkedin.com/marketing-solutions/conversion-tracking)
29
+ - [etracker](https://www.etracker.com)
30
+ - [matomo analytics](https://matomo.org)
31
+ - [smartlook](https://www.smartlook.com)
32
+ - [crazy egg](https://www.crazyegg.com)
33
+ - [google maps](https://developers.google.com/maps/documentation/javascript/tutorial)
34
+
35
+ ## installation
36
+
37
+ use it as a module:
38
+
39
+ ```
40
+ npm install chefcookie
41
+ ```
42
+
43
+ ```js
44
+ import chefcookie from 'chefcookie';
45
+ ```
46
+
47
+ or include it the traditional way:
48
+
49
+ ```html
50
+ <script src="chefcookie.min.js"></script>
51
+ ```
52
+
53
+ ## usage
54
+
55
+ ```js
56
+ const cc = new chefcookie({
57
+ message: {
58
+ de: `
59
+ <h2>Wir verwenden Cookies</h2>
60
+ <p>
61
+ Unsere Website verwendet Cookies, die uns helfen, unsere Website zu verbessern, den bestmöglichen Service zu bieten und ein optimales Kundenerlebnis zu ermöglichen. <a href="#chefcookie__settings">Hier</a> können Sie Ihre Einstellungen verwalten. Indem Sie auf "<a href="#chefcookie__accept">Akzeptieren</a>" klicken, erklären Sie sich damit einverstanden, dass Ihre Cookies für diesen Zweck verwendet werden. Weitere Informationen dazu finden Sie in unserer <a href="/de/datenschutz">Datenschutzerklärung</a> sowie im <a href="/de/impressum">Impressum</a>. Sollten Sie hiermit nicht einverstanden sein, können Sie die Verwendung von Cookies hier <a href="#chefcookie__decline">ablehnen</a>.
62
+ </p>
63
+ `,
64
+ en: `
65
+ <h2>We use cookies</h2>
66
+ <p>
67
+ Our website uses cookies that help us to improve our website, provide the best possible service and enable an optimal customer experience. <a href="#chefcookie__settings">Here</a> you can manage your settings. By clicking on "<a href="#chefcookie__accept">Accept</a>", you agree that your cookies may be used for this purpose. You can find further information on this in our <a href="/en/privacy">data protection declaration</a> and in the <a href="/en/imprint">imprint</a>. If you do not agree to this, you can refuse the use of cookies here <a href="#chefcookie__decline">reject</a> the use of cookies.
68
+ </p>
69
+ `
70
+ },
71
+ accept_all_if_settings_closed: true,
72
+ show_decline_button: false,
73
+ scripts_selection: 'collapse', // false|true|'collapse'
74
+ debug_log: false,
75
+ consent_tracking: null, // '/wp-json/v1/track-consent.php'
76
+ expiration: 7, // in days
77
+ exclude_google_pagespeed: true,
78
+ style: {
79
+ layout: 'overlay', // overlay|bottombar|topbar
80
+ size: 3, // 1|2|3|4|5
81
+ color_text: '#595f60',
82
+ color_highlight: '#ff0000',
83
+ color_background: '#eeeeee',
84
+ highlight_accept: true,
85
+ show_disabled_checkbox: true,
86
+ noscroll: true,
87
+ fade: true,
88
+ blur: true,
89
+ css_replace: ``, // replace plugin's styles with custom css
90
+ css_add: `` // enhance plugin's styles with custom css
91
+ },
92
+ labels: {
93
+ accept: { de: 'Akzeptieren', en: 'Accept' },
94
+ accept_all: { de: 'Alles akzeptieren', en: 'Accept all' },
95
+ settings_open: { de: 'Einstellungen festlegen', en: 'Change settings' },
96
+ settings_close: { de: 'Einstellungen schliessen', en: 'Close settings' },
97
+ group_open: { de: 'Weitere Informationen anzeigen', en: 'Show more information' },
98
+ group_close: { de: 'Weitere Informationen schliessen', en: 'Close more information' },
99
+ decline: { de: 'Nur erforderliche Cookies', en: 'Only necessary cookies' },
100
+ details_open: { de: 'Details anzeigen', en: 'Show details' },
101
+ details_close: { de: 'Details schliessen', en: 'Close details' }
102
+ },
103
+ exclude: [
104
+ // exclude privacy site if needed
105
+ '/de/datenschutz',
106
+ '/en/privacy',
107
+ '/de/impressum',
108
+ '/en/imprint',
109
+ // exclude wordpress users
110
+ () => {
111
+ return document.cookie !== undefined && document.cookie.indexOf('wp-settings-time') > -1;
112
+ }
113
+ ],
114
+ settings: [
115
+ {
116
+ title: { de: 'Analysen', en: 'Analyses' },
117
+ description: {
118
+ de: 'Tools, die anonyme Daten über Website-Nutzung und -Funktionalität sammeln. Wir nutzen die Erkenntnisse, um unsere Produkte, Dienstleistungen und das Benutzererlebnis zu verbessern.',
119
+ en: 'Tools that collect anonymous data about website usage and functionality. We use this information to improve our products, services and user experience.'
120
+ },
121
+ checked_by_default: true,
122
+ cannot_be_modified: false,
123
+ initial_tracking: false,
124
+ scripts: {
125
+ analytics: 'UA-xxxxxxxx-1',
126
+ // extended syntax
127
+ analytics: {
128
+ id: 'UA-xxxxxxxx-1',
129
+ title: { de: 'Google Analytics', en: 'Google Analytics' },
130
+ description: {
131
+ de: 'Die Verwendung der Analyse Cookies erfolgt zu dem Zweck, die Qualität unserer Website und ihre Inhalte zu verbessern und die Funktionsfähigkeit von eingebundenen Diensten unserer Partner sicherzustellen.',
132
+ en: `
133
+ <p>
134
+ Google Analytics cookies are used to improve the quality of our website and its content and to ensure the functionality of integrated services of our partners.
135
+ </p>
136
+ <table>
137
+ <tr><td>Name:</td><td>_gid</td></tr>
138
+ <tr><td>Host:</td><td>www.tld.com</td></tr>
139
+ <tr><td>Duration:</td><td>Session</td></tr>
140
+ <tr><td>Type:</td><td>1st Party</td></tr>
141
+ <tr><td>Description:</td><td>This is a pattern type cookie name associated with a marketing cloud. It stores an unique visitor identifier, and uses an organisation identifier.</td></tr>
142
+ </table>
143
+ `
144
+ }
145
+ }
146
+ }
147
+ },
148
+ {
149
+ title: { de: 'Werbung', en: 'Advertising' },
150
+ description: {
151
+ de: 'Anonyme Informationen, die wir sammeln, um Ihnen nützliche Produkte und Dienstleistungen empfehlen zu können.',
152
+ en: 'Anonymous information that we collect in order to recommend useful products and services to you.'
153
+ },
154
+ checked_by_default: true,
155
+ cannot_be_modified: false,
156
+ initial_tracking: false,
157
+ scripts: {
158
+ tagmanager: 'GTM-XXXXXXX',
159
+ facebook: 'xxxxxxxxxxxxxxx',
160
+ twitter: 'single',
161
+ taboola: 'xxxxxxx',
162
+ match2one: 'xxxxxxxx',
163
+ linkedin: 'xxxxxxx',
164
+ etracker: 'xxxxxx',
165
+ matomo: 'xxxxxx#x', // domain/siteid
166
+ smartlook: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
167
+ crazyegg: 'xxxx/xxxx',
168
+ google_maps: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
169
+ }
170
+ },
171
+ {
172
+ title: { de: 'Drittanbieter', en: 'Third-party' },
173
+ description: {
174
+ de: 'Tools, die interaktive Services wie beispielsweise Video- und Kartendienste unterstützen.',
175
+ en: 'Tools that support interactive services such as video and map services.'
176
+ },
177
+ checked_by_default: true,
178
+ cannot_be_modified: false,
179
+ initial_tracking: false,
180
+ scripts: {}
181
+ },
182
+ {
183
+ title: { de: 'Grundlegendes', en: 'Basics' },
184
+ description: {
185
+ de: 'Tools, die wesentliche Services und Funktionen ermöglichen, einschließlich Identitätsprüfung, Servicekontinuität und Standortsicherheit. Diese Option kann nicht abgelehnt werden.',
186
+ en: 'Tools that enable essential services and functions, including identity verification, service continuity, and site security. This option cannot be declined.'
187
+ },
188
+ checked_by_default: true,
189
+ cannot_be_modified: true,
190
+ initial_tracking: true,
191
+ scripts: {
192
+ example_script1: {}, // this immediately gets "resolved"
193
+ example_script2: {
194
+ accept: (cc, resolve, isInit) => {
195
+ /* example: load default scripts inside custom script */
196
+ cc.load('analytics', 'UA-xxxxxxxx-1');
197
+ cc.load('tagmanager', 'GTM-XXXXXXX');
198
+ cc.load('facebook', 'xxxxxxxxxxxxxxx');
199
+ cc.load('twitter', 'single');
200
+ cc.load('taboola', 'xxxxxxx');
201
+ cc.load('match2one', 'xxxxxxxx');
202
+ cc.load('linkedin', 'xxxxxxx');
203
+ cc.load('etracker', 'xxxxxx');
204
+ cc.load('matomo', 'xxxxxx#x');
205
+ cc.load('smartlook', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
206
+ cc.load('crazyegg', 'xxxx/xxxx');
207
+ cc.load('google_maps', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
208
+
209
+ /* example: load (multiple) custom javascripts */
210
+ cc.loadJs([
211
+ 'script1.js',
212
+ 'script2.js',
213
+ 'https://www.googletagmanager.com/gtag/js?id=UA-xxxxxxxx-1'
214
+ ]).then(() => {
215
+ resolve();
216
+ });
217
+
218
+ /* example: enable uninitialized iframes */
219
+ if (document.querySelector('iframe[alt-src*="google.com/maps"]') !== null) {
220
+ document.querySelectorAll('iframe[alt-src*="google.com/maps"]').forEach(el => {
221
+ el.setAttribute('src', el.getAttribute('alt-src'));
222
+ });
223
+ }
224
+
225
+ /* example: load scripts manually */
226
+ let script1 = document.createElement('script');
227
+ script1.setAttribute('src', 'https://www.googletagmanager.com/gtag/js?id=UA-xxxxxxxx-1');
228
+ script1.onload = () => {
229
+ resolve();
230
+ };
231
+ document.head.appendChild(script1);
232
+
233
+ /* example: load scripts manually */
234
+ let script2 = document.createElement('script');
235
+ let html = "alert('OK');";
236
+ script2.innerHTML = html;
237
+ document.head.appendChild(script2);
238
+
239
+ /* example: load scripts manually (with custom callback) */
240
+ window.captchaCallback = () => {
241
+ resolve();
242
+ };
243
+ cc.loadJs('https://www.google.com/recaptcha/api.js?onload=captchaCallback&amp;render=explicit');
244
+
245
+ /*
246
+ important: always call resolve to show that the script fully has loaded!
247
+ if you don't want the accept logic to be inside this function, only call resolve() and use waitFor outside this function to fire further actions */
248
+ resolve();
249
+
250
+ /* some other helpers */
251
+ cc.url(); // gets the current url
252
+ cc.lng(); // gets the current lng
253
+ isInit; // true|false (accepted actively through click and not via cookie)
254
+ },
255
+ exclude: () => {
256
+ return document.cookie !== undefined && document.cookie.indexOf('wp-settings-time') > -1;
257
+ },
258
+ title: { de: '...', en: '...' },
259
+ description: { de: '...', en: '...' }
260
+ }
261
+ }
262
+ }
263
+ ]
264
+ });
265
+ document.addEventListener('DOMContentLoaded', () => {
266
+ cc.init();
267
+ });
268
+ ```
269
+
270
+ #### multi language support
271
+
272
+ instead of plain text you can provide language objects for any label:
273
+
274
+ ```js
275
+ {
276
+ title: 'Werbung';
277
+ }
278
+ ```
279
+
280
+ ```js
281
+ {
282
+ title: { de: 'Werbung', en: 'Advertising' }
283
+ }
284
+ ```
285
+
286
+ chefcookie will find out the current language and show the appropriate strings.
287
+
288
+ #### opt out links
289
+
290
+ its recommended to place those kind of links inside your privacy page:
291
+
292
+ ```html
293
+ <a href="#" data-cc-disable="analytics" data-cc-message="Google Analytics aktivieren">Google Analytics deaktivieren</a>
294
+ <a href="#" data-cc-disable="tagmanager" data-cc-message="Google Tag Manager aktivieren"
295
+ >Google Tag Manager deaktivieren</a
296
+ >
297
+ <a href="#" data-cc-disable="facebook" data-cc-message="Facebook Pixel aktivieren">Facebook Pixel deaktivieren</a>
298
+ <a href="#" data-cc-disable="twitter" data-cc-message="Twitter Pixel aktivieren">Twitter Pixel deaktivieren</a>
299
+ <a href="#" data-cc-disable="taboola" data-cc-message="Taboola Pixel aktivieren">Taboola Pixel deaktivieren</a>
300
+ <a href="#" data-cc-disable="match2one" data-cc-message="Match2One Pixel aktivieren">Match2One Pixel deaktivieren</a>
301
+ <a href="#" data-cc-disable="linkedin" data-cc-message="LinkedIn Pixel aktivieren">LinkedIn Pixel deaktivieren</a>
302
+ <a href="#" data-cc-disable="etracker" data-cc-message="etracker aktivieren">etracker deaktivieren</a>
303
+ <a href="#" data-cc-disable="matomo" data-cc-message="Matomo aktivieren">Matomo deaktivieren</a>
304
+ <a href="#" data-cc-disable="smartlook" data-cc-message="Smartlook aktivieren">Smartlook deaktivieren</a>
305
+ <a href="#" data-cc-disable="crazyegg" data-cc-message="Crazy Egg aktivieren">Crazy Egg deaktivieren</a>
306
+ <a href="#" data-cc-disable="google_maps" data-cc-message="Google Maps aktivieren">Google Maps deaktivieren</a>
307
+ ```
308
+
309
+ you can style those links with:
310
+
311
+ ```css
312
+ [data-cc-disable] {
313
+ }
314
+ [data-cc-disable].disabled {
315
+ }
316
+ ```
317
+
318
+ #### (one time) opt in links
319
+
320
+ these links self destroy if the respective script is accepted:
321
+
322
+ ```html
323
+ <div data-cc-enable="google_maps">
324
+ Ich möchte Google Maps-Inhalte aktivieren und stimme zu, dass Daten von Google geladen werden (siehe
325
+ <a href="/de/datenschutz" target="_blank">Datenschutz</a>).
326
+ </div>
327
+ ```
328
+
329
+ it is recommended to place them inside your via js populated divs (like a google maps wrapper).\
330
+ if you click on it, the script is explicitly accepted.
331
+
332
+ #### manually accept/decline
333
+
334
+ ```js
335
+ cc.accept('analytics');
336
+ cc.decline('analytics');
337
+ cc.isAccepted('analytics'); // true|false
338
+ ```
339
+
340
+ #### backdoor
341
+
342
+ just add `?accept=1` to your urls to completely bypass chefcookie.
343
+
344
+ #### custom scripts
345
+
346
+ the following keywords as keys are reserved:
347
+
348
+ - `analytics`
349
+ - `tagmanager`
350
+ - `facebook`
351
+ - `twitter`
352
+ - `taboola`
353
+ - `match2one`
354
+ - `linkedin`
355
+ - `etracker`
356
+ - `matomo`
357
+ - `smartlook`
358
+ - `crazyegg`
359
+ - `google_maps`
360
+
361
+ if you provide strings as values, chefcookie interprets them appropriately. chefcookie then loads the libraries with reasonable default settings. however, you can execute your own functions in either overwriting the values of these reserved keywords (and provide an object) or use any other keyword.
362
+
363
+ #### script blocking
364
+
365
+ the best strategy is to add no scripts at all and let chefcookie add the scripts later.
366
+
367
+ if you cannot do that (e.g. when you cannot manipulate the page content), there are a lot of techniques and strategies out there to prevent existing scripts from executing:
368
+
369
+ - use http content-security-policy headers
370
+ - manipulate embeds (set `type="javascript/blocked"` or `alt-src="..."`)
371
+ - monkey patch `document.createElement`
372
+ - watch and modify with `MutationObserver`
373
+ - abuse `document.write`
374
+
375
+ chefcookie is flexible and very well works together with e.g. [yett](https://github.com/snipsco/yett):
376
+
377
+ - init `yett` before chefcookie to block scripts
378
+ - call `unblock()` inside chefcookies custom scripts
379
+
380
+ #### dynamically load a script
381
+
382
+ chefcookie provides a `load`-helper, where you can provide one or multiple urls to load:
383
+
384
+ ```js
385
+ cc.loadJs(['script1.js', 'script2.js']);
386
+ ```
387
+
388
+ in order to call `resolve()` (see below), you can use:
389
+
390
+ ```js
391
+ cc.loadJs(['script1.js', 'script2.js']).then(() => { resolve(); };
392
+ cc.loadJs(['script1.js', 'script2.js'], () => { resolve(); }); // also supported
393
+ ```
394
+
395
+ #### wait for a tracker
396
+
397
+ if your javascript is dependent on a specific script loaded by chefcookie, you should handle that case and wait for the tracker being executed:
398
+
399
+ ```js
400
+ cc.waitFor('google_recaptcha').then(() => {});
401
+ cc.waitFor('google_recaptcha', () => {}); // also supported
402
+ ```
403
+
404
+ this only gets executed when you call `resolve()` inside your custom tracking function.
405
+
406
+ #### more
407
+
408
+ the cookie banner is shown always, if no consent is saved.\
409
+ if done so, it is shown again, after the cookie expired (see the `expiration`-setting).
410
+
411
+ it is recommended to include a (re)opening link in the privacy policy, for example.\
412
+ here you can also use the following code:
413
+
414
+ ```html
415
+ <a href="#" data-cc-open>Consent-Einstellungen bearbeiten</a>
416
+ ```
417
+
418
+ you can programmatically control chefcookie via javascript:
419
+
420
+ - `cc.open()`: open the cookie banner manually
421
+ - `cc.isOpen()`: check if cookie banner is opened
422
+ - `cc.close()`: close the cookie banner manually
423
+ - `cc.destroy()`: destroy the cookie banner and all event listeners
424
+ - `cc.updateOptOutOptIn()`: refreshes the state of opt out / opt in buttons
425
+
426
+ #### consent manager tracking
427
+
428
+ to test the acceptance of the consent manager, it is recommended to use the `consent_tracking`-option. if you specify an url (relative or absolute) there, chefcookie sends a post-request with analysis data for every action that a user performs in the consent manager. these requests have the form:
429
+
430
+ ```json
431
+ {
432
+ "action": "accept_all",
433
+ "date": "2021-01-01 10:00:00",
434
+ "url": "https://tld.com?foo=bar",
435
+ "providers": "analytics,facebook,twitter",
436
+ "viewport": "the viewport size of the user device"
437
+ }
438
+ ```
439
+
440
+ `url` as you can see consists of potential get-paramaters (so that you can analyze e.g. google ads campaigns).\
441
+ take note that nor ip or user agent are posted, but feel free to catch and store these parts with the help of a php endpoint.
442
+
443
+ the `action`-key can have the following values:
444
+
445
+ - `open`: the consent manager is shown
446
+ - `accept_all`: all providers are accepted
447
+ - `accept_partially`: providers are accepted partially
448
+ - `decline`: all providers are declined
449
+ - `settings_open`: settings are opened
450
+ - `settings_close`: settings are closed
451
+ - `first_user_interaction`: first mouse/touch/scroll interaction happened
452
+
453
+ here it makes sense to temporarily store this data in a database and evaluate it – for example, to measure the discrepancy between the real visitor numbers and the numbers in google analytics or to optimize the appearance of the consent manager (e.g. using the `layout`-option).
454
+
455
+ #### event tracking
456
+
457
+ chefcookie additionally comes with event tracking for all major analytics platforms.\
458
+ you can even use this feature with side loaded scripts.
459
+
460
+ ```js
461
+ window.addEventListener('load', () => {
462
+ // track duration (sends action "xxs" in 30 second intervals)
463
+ cc.trackDuration();
464
+ // track scroll depth (sends "xx%" in scroll steps 1, 10, 25, 50, 75, 100)
465
+ cc.trackScrollDepth();
466
+ // custom duration
467
+ cc.trackDurationCustom(60, () => {
468
+ cc.eventAnalytics('60s');
469
+ });
470
+ // custom scroll depth
471
+ cc.trackScrollDepthCustom(25, () => {
472
+ cc.eventAnalytics('25%');
473
+ });
474
+ // custom tracking
475
+ document.querySelector('.conversion').addEventListener('click', e => {
476
+ cc.eventAnalytics('custom_category', 'custom_action');
477
+ cc.eventAnalytics('custom_action');
478
+ cc.eventFacebook('custom_action_name');
479
+ cc.eventTwitter('conversion_id');
480
+ cc.eventTaboola('custom_event_name');
481
+ cc.eventMatch2one('id=xxxxxx&seg=xxxxxx');
482
+ cc.eventLinkedin('id', 'conversion_id');
483
+ cc.eventEtracker('custom_category', 'custom_action');
484
+ cc.eventEtracker('custom_action');
485
+ e.preventDefault();
486
+ });
487
+ });
488
+ ```