PageSourceSearch

https://www.lawrence.edu/wp-content/mu-plugins/lu-analytics/js/klaro-config.js?ver=1.0.12

js lawrence.edu collected 2026-09-24 08:47:55 UTC 6,555 bytes, 184 lines download raw bytes

1/**
2 * Klaro configuration — based on the live Drupal setup, with an opt-out gate.
3 *
4 * Defines the global `window.klaroConfig` that the vendored Klaro.js reads on
5 * load (it auto-renders from the `klaroConfig` global). Most values copy the
6 * Drupal `config/sync/klaro.*.yml` (notice mode, cookie "klaro"/180-day, light
7 * theme, group_by_purpose off, the "Cookie Notice" title and "We use cookies…"
8 * wording).
9 *
10 * Deliberate divergence from Drupal: the notice now shows a **Reject** button
11 * (`hideDeclineAll: false`) and Google Analytics + Tag Manager are **opt-out**
12 * (`required: false`, `default: true`) instead of always-on `required: true`.
13 * They run by default but a visitor can reject them. The enforcement is in the
14 * container module: the GTM snippet is emitted with contextual-blocking markup
15 * (`type="text/plain" data-name="gtm"`) so Klaro only executes it while the
16 * `gtm` service is consented — reject stops GTM, and therefore GA and every
17 * downstream marketing pixel it fires. Essential services (functional, consent
18 * manager, reCAPTCHA) stay `required: true`. The five embeds remain opt-in.
19 */
20( function () {
21	'use strict';
22
23	var data = window.luKlaro || {};
24	var privacyUrl = data.privacyUrl || '/privacy-policy';
25
26	window.klaroConfig = {
27		version: 1,
28		elementID: 'klaro',
29		styling: { theme: [ 'light' ] },
30		noAutoLoad: false,
31		htmlTexts: true,
32		embedded: false,
33		groupByPurpose: false,
34		storageMethod: 'cookie',
35		cookieName: 'klaro',
36		cookieExpiresAfterDays: 180,
37		default: false,
38		mustConsent: false,
39		acceptAll: true,
40		hideDeclineAll: false,
41		hideLearnMore: true,
42		privacyPolicy: privacyUrl,
43
44		translations: {
45			en: {
46				consentModal: {
47					title: 'Use of personal data and cookies',
48					description: 'Please choose the services and 3rd party applications we would like to use.'
49				},
50				consentNotice: {
51					title: 'Cookie Notice',
52					description: 'We use cookies on this site. By continuing to browse without changing your browser settings to block or delete cookies, you agree to the {privacyPolicy}.',
53					changeDescription: 'There were changes since your last visit, please update your consent.',
54					learnMore: 'Customize'
55				},
56				privacyPolicy: {
57					name: 'Lawrence Privacy Policy',
58					text: 'To learn more, please read our {privacyPolicy}.'
59				},
60				ok: 'Accept',
61				save: 'Save',
62				decline: 'Reject',
63				close: 'Close',
64				acceptAll: 'Accept all',
65				acceptSelected: 'Accept selected',
66				purposes: {
67					cms: 'Functional',
68					analytics: 'Analytics',
69					advertising: 'Advertising and Marketing',
70					security: 'Security',
71					external_content: 'Embedded external content'
72				},
73				service: {
74					disableAll: {
75						title: 'Toggle all services',
76						description: 'Use this switch to enable/disable all services.'
77					},
78					optOut: {
79						title: '(opt-out)',
80						description: 'This service is loaded by default (opt-out possible).'
81					},
82					required: {
83						title: '(always required)',
84						description: 'This service is always required.'
85					},
86					purposes: 'Purposes',
87					purpose: 'Purpose'
88				},
89				poweredBy: 'Powered by Klaro!'
90			}
91		},
92
93		// Service NAMES + the full set are kept identical to the live Drupal
94		// Klaro apps (config/sync/klaro.klaro_app.*.yml where status: true): the
95		// consent cookie stores a { serviceName: boolean } map keyed by these
96		// `name`s, so matching them lets a visitor's saved consent carry over at
97		// cutover without re-prompting. Adding, removing, or renaming a service
98		// re-prompts returning visitors. The `required` flags on `ga`/`gtm`
99		// deliberately differ from Drupal (opt-out, not always-on) — that changes
100		// behaviour, not the cookie shape, so carry-over still holds.
101		services: [
102			{
103				name: 'cms',
104				title: 'Functional',
105				purposes: [ 'cms' ],
106				required: true,
107				default: true,
108				cookies: [ /^_?Ss?ESS/ ]
109			},
110			{
111				name: 'klaro',
112				title: 'Consent manager',
113				purposes: [ 'cms' ],
114				required: true,
115				default: true,
116				cookies: [ /^klaro/ ]
117			},
118			{
119				name: 'google_recaptcha',
120				title: 'Google reCAPTCHA',
121				purposes: [ 'security' ],
122				required: true,
123				default: true
124			},
125			// Opt-out: loaded by default but rejectable. `gtm` gates the GTM
126			// snippet (contextual blocking in container/namespace.php); `ga` is
127			// declared for cookie management and consent display — GA fires via
128			// the container, so rejecting `gtm` already stops it.
129			{
130				name: 'ga',
131				title: 'Google Analytics',
132				purposes: [ 'analytics' ],
133				required: false,
134				default: true,
135				cookies: [ /^_ga(_.*)?$/, /^_gid$/, /^IDE$/ ]
136			},
137			{
138				name: 'gtm',
139				title: 'Google Tag Manager',
140				purposes: [ 'advertising' ],
141				required: false,
142				default: true
143			},
144			{ name: 'facebook', title: 'Facebook', purposes: [ 'external_content' ], default: false },
145			{ name: 'linkedin', title: 'Linkedin', purposes: [ 'external_content' ], default: false },
146			{ name: 'tiktok', title: 'TikTok', purposes: [ 'external_content' ], default: false },
147			{ name: 'vimeo', title: 'Vimeo', purposes: [ 'external_content' ], default: false },
148			{ name: 'youtube', title: 'YouTube', purposes: [ 'external_content' ], default: false }
149		]
150	};
151
152	// Klaro 0.7 does not render the notice's title (it only sets
153	// aria-labelledby="id-cookie-title", referencing an element it never
154	// creates). The live Drupal site shows the title (show_notice_title), so we
155	// inject it once Klaro renders the notice — matching Drupal and resolving the
156	// dangling aria reference. Styled by the `.title` rule in css/klaro.css.
157	var noticeTitle = window.klaroConfig.translations.en.consentNotice.title;
158
159	function injectNoticeTitle() {
160		var body = document.querySelector( '#klaro-cookie-notice .cn-body' );
161		if ( ! body || document.getElementById( 'id-cookie-title' ) ) {
162			return ! ! document.getElementById( 'id-cookie-title' );
163		}
164		var heading = document.createElement( 'div' );
165		heading.id = 'id-cookie-title';
166		heading.className = 'title';
167		heading.textContent = noticeTitle;
168		body.insertBefore( heading, body.firstChild );
169		return true;
170	}
171
172	if ( ! injectNoticeTitle() ) {
173		var observer = new MutationObserver( function () {
174			if ( injectNoticeTitle() ) {
175				observer.disconnect();
176			}
177		} );
178		observer.observe( document.documentElement, { childList: true, subtree: true } );
179		// Klaro renders on load; stop watching after a short window regardless.
180		setTimeout( function () {
181			observer.disconnect();
182		}, 10000 );
183	}
184} )();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.