PageSourceSearch

https://smartus.hu/wp-content/plugins/faz-cookie-manager/frontend/js/gcm.js?ver=1.33.0

js smartus.hu collected 2026-10-07 19:00:29 UTC 17,231 bytes, 363 lines download raw bytes

1(function () {
2"use strict";
3
4var data = window._fazGcm;
5if (!data) {
6    return;
7}
8var setDefaultSetting = true;
9var regionSettings = Array.isArray(data.default_settings) ? data.default_settings : [];
10var waitForTime = data.wait_for_update || 0;
11
12function getCookieValues(cookieName) {
13    var values = [];
14    var name = cookieName + "=";
15    var parts = document.cookie.split(';');
16
17    for (var i = 0; i < parts.length; i++) {
18        var cookie = parts[i];
19        while (cookie.charAt(0) === ' ') {
20            cookie = cookie.substring(1);
21        }
22        if (cookie.indexOf(name) === 0) {
23            var raw = cookie.substring(name.length, cookie.length);
24            try {
25                values.push(decodeURIComponent(raw));
26            } catch (e) {
27                values.push(raw);
28            }
29        }
30    }
31    return values;
32}
33
34function getConsentStateForCategory(categoryConsent) {
35    return categoryConsent === "yes" ? "granted" : "denied";
36}
37
38var dataLayerName =
39  data.data_layer_name ||
40  (window.fazSettings && window.fazSettings.dataLayerName) ||
41  "dataLayer";
42window[dataLayerName] = window[dataLayerName] || [];
43function gtag() {
44    window[dataLayerName].push(arguments);
45}
46
47function setConsentInitStates(consentData) {
48    // Advanced Consent Mode (#165): the synchronous denied `consent default`
49    // is already emitted inline in <head> (print_gcm_default_inline) so it
50    // runs before the page's gtag snippet. Skip here so we never emit a
51    // SECOND `consent default`, which Consent Mode tooling flags as resetting
52    // consent (issue #149). The `consent update` path is unchanged.
53    if (data.advanced_mode) return;
54    if (waitForTime > 0) consentData.wait_for_update = waitForTime;
55    gtag("consent", "default", consentData);
56}
57
58// Non-personalized-ads fallback signal for LEGACY (non-Consent-Mode) ad tags,
59// which don't read ad_storage. When the publisher enabled the fallback, mirror
60// the ad_storage decision into `npa`: 1 (non-personalized) while ad_storage is
61// denied, 0 once granted. Two-sided + called from every path (first-visit
62// default, region rows, and the post-action update) so the signal is consistent
63// and self-clears within the session — Consent Mode v2 tags already read
64// ad_storage directly.
65function setNpaIfDenied(adStorage) {
66    if (!data || !data.non_personalized_ads_fallback) return;
67    gtag("set", { npa: adStorage === "denied" ? 1 : 0 });
68}
69
70// In Advanced Consent Mode these are already emitted by the synchronous
71// inline <head> bootstrap (print_gcm_default_inline); skip here to avoid a
72// duplicate set (#165 F6). Both paths use the same dataLayer array (F4), so
73// the skip is purely cosmetic, but keeping a single emitter is cleaner.
74if (!data.advanced_mode) {
75    gtag("set", "ads_data_redaction", !!data.ads_data_redaction);
76    gtag("set", "url_passthrough", !!data.url_passthrough);
77}
78
79// IMPORTANT: we must parse the consent cookie BEFORE emitting any consent
80// states. We follow the standard Consent Mode pattern (matching CookieYes
81// upstream): a single baseline `consent default` (region-specific / denied,
82// carrying wait_for_update), then — for a returning visitor with a stored
83// cookie — a `consent update` carrying their granted states. wait_for_update
84// holds ad tags (AdSense, GTM) until the update lands, so there is no
85// denied-ad race. Emitting a SECOND `consent default` with granted values
86// instead is flagged by Consent Mode tooling as resetting consent (issue #149).
87//
88// Order matters:
89//   1. parseConsentCookie() -> read cookie synchronously
90//   2.  emit the region-specific / denied baseline `consent default`
91//       (Basic mode). In Advanced Consent Mode (#165) this step is SKIPPED
92//       here — setConsentInitStates() early-returns — because the denied
93//       baseline is already emitted synchronously in <head> by
94//       print_gcm_default_inline(), as a single GLOBAL most-restrictive
95//       default rather than per-region.
96//   3.  if cookie present -> emit `consent update` with the stored grants
97//
98// FAZ_META_KEYS must be declared BEFORE this call: parseConsentCookie() reads
99// it, and although the function is hoisted, the `var` only hoists the
100// declaration (not the value). Declaring it lower in the file left it
101// `undefined` at this call site, so a returning visitor (or a PMP-exempt member
102// with an auto-granted cookie) hit "Cannot read properties of undefined" on the
103// first key and gcm.js threw before emitting any consent.
104// Non-category meta keys stored in the consent cookie (not consent states).
105// `gpc` flags a consent recorded automatically from a Global Privacy Control
106// signal; like rev/action/consentid it must not be coerced to granted/denied.
107var FAZ_META_KEYS = { rev: 1, action: 1, consentid: 1, gpc: 1 };
108
109var initialCookieObj = parseConsentCookie();
110
111// Baseline consent DEFAULT (region-specific / denied) is emitted first in
112// Basic mode — for first-time AND returning visitors. (In Advanced Consent
113// Mode it is emitted synchronously in <head> instead; setConsentInitStates()
114// below no-ops.) Consent Mode expects exactly one
115// well-formed `consent default` before any update; emitting a SECOND
116// `consent default` with granted values to restore a returning visitor (issue
117// #149) is flagged by Consent Mode tooling as resetting consent. The returning
118// visitor's stored grants are restored via `consent update` below instead — the
119// brief denied window is covered by wait_for_update on this baseline default.
120{
121    // Region-specific defaults as configured by the admin.
122    //
123    // ad_storage stays at the admin-configured (typically "denied") regi
123on
124    // value before the visitor interacts. The "non-personalized ads fallback"
125    // does NOT grant ad_storage (that would write ad cookies without consent —
126    // unlawful under ePrivacy/Consent Mode v2 in EEA/UK/CH). Under Consent Mode
127    // v2 a denied ad_storage already lets Google serve non-personalized,
128    // cookieless ads; for legacy (non-Consent-Mode) ad tags we additionally
129    // signal `npa`. Unlike the Consent Mode `ad_storage` states above, `npa` is
130    // a GLOBAL gtag('set') value — it CANNOT be region-scoped — so emitting it
131    // per region row would let the last-iterated row win for everyone. Instead
132    // we track the most-restrictive ad stance across all applicable defaults and
133    // emit `npa` ONCE after the loop: npa:1 if ANY default denies ads. This
134    // protects denied regions from personalized legacy ads pre-consent without
135    // geofencing. buildConsentState() (update path) re-evaluates `npa` two-sided
136    // from the returning visitor's real choice.
137    var anyAdDenied = false;
138    for (var index = 0; index < regionSettings.length; index++) {
139        var regionSetting = regionSettings[index];
140        if (!regionSetting || typeof regionSetting !== "object") continue;
141        // Read the category-mirror keys: these are the source of truth for the
142        // storage-type signals. The non-personalized-ads fallback deliberately
143        // keeps the `marketing` mirror and the canonical `ad_storage` OUT of sync
144        // (marketing drives ad serving here), so reading the mirrors is
145        // load-bearing — do NOT switch this to canonical-first. The runtime
146        // geo-routing override writes these same mirror keys (see
147        // Geo_Runtime::apply_cmv2_to_gcm) so its CMv2 signals reach gtag too.
148        var consentRegionData = {
149            ad_storage: regionSetting.marketing || regionSetting.advertisement || "denied",
150            analytics_storage: regionSetting.analytics,
151            functionality_storage: regionSetting.functional,
152            personalization_storage: regionSetting.functional,
153            security_storage: regionSetting.necessary,
154            ad_user_data: regionSetting.ad_user_data,
155            ad_personalization: regionSetting.ad_personalization
156        };
157        var regionsRaw = typeof regionSetting.regions === "string" ? regionSetting.regions : "";
158        var regionsToSetFor = regionsRaw
159            .split(",")
160            .map(function (region) { return region.trim(); })
161            .filter(function (region) { return region; });
162        if (regionsToSetFor.length > 0 && regionsToSetFor[0].toLowerCase() !== "all")
163            consentRegionData.region = regionsToSetFor;
164        else setDefaultSetting = false;
165        setConsentInitStates(consentRegionData);
166        if (consentRegionData.ad_storage === "denied") anyAdDenied = true;
167    }
168
169    if (setDefaultSetting) {
170        setConsentInitStates({
171          ad_storage: "denied",
172          analytics_storage: "denied",
173          functionality_storage: "denied",
174          personalization_storage: "denied",
175          security_storage: "granted",
176          ad_user_data: "denied",
177          ad_personalization: "denied"
178        });
179        anyAdDenied = true;
180    }
181
182    // Single global npa for the pre-consent default stage (see comment above):
183    // most-restrictive wins, since gtag('set', { npa }) is not region-scoped.
184    setNpaIfDenied(anyAdDenied ? "denied" : "granted");
185}
186
187// Returning visitor with saved consent: restore it via `consent update` (the
188// GCM-correct restoration signal), NOT a second `consent default`.
189// buildConsentState() also emits the non-personalized-ads npa signal (two-sided)
190// so it self-clears here when marketing was granted.
191if (initialCookieObj) {
192    updateConsentState(buildConsentState(initialCookieObj));
193}
194
195function parseConsentCookieParts() {
196    var raw = getCookieValues("fazcookie-consent")[0];
197    if (!raw || typeof raw !== "string") return null;
198    return raw.split(",").reduce(function (acc, curr) {
199        var trimmed = curr.trim();
200        // Match PHP's faz_parse_consent_cookie() which uses
201        // explode(':', $pair, 2) — split on the FIRST colon, not the last,
202        // so values containing colons (e.g. a future "source:pmp:L2" token)
203        // round-trip consistently between server and client.
204        var sepIdx = trimmed.indexOf(":");
205        if (sepIdx === -1) return acc;
206        var key = trimmed.substring(0, sepIdx).trim();
207        if (!key) return acc;
208        acc[key] = trimmed.substring(sepIdx + 1).trim();
209        return acc;
210    }, {});
211}
212
213function isConsentCookieStale(parsed) {
214    if (!parsed) return false;
215    var config = window._fazConfig || {};
216    // wp_localize_script often stringifies numeric values ("1" instead of 1),
217    // so we can't rely on typeof === "number". Coerce and fall back to 1.
218    var serverRevisionRaw = config && config._consentRevision;
219    var serverRevision = parseInt(serverRevisionRaw, 10);
220    if (isNaN(serverRevision) || serverRevision < 1) serverRevision = 1;
221    var storedRevision = parseInt(parsed.rev, 10);
222    return serverRevision > 1 && (isNaN(storedRevision) || storedRevision < serverRevision);
223}
224
225function parseConsentCookie() {
226    var parsed = parseConsentCookieParts();
227    if (!parsed || isConsentCookieStale(parsed)) return null;
228    Object.keys(parsed).forEach(function(key) {
229        // Leave meta keys (rev/action/consentid) as their raw value; only
230        // category slugs are coerced to granted/denied.
231        if (!FAZ_META_KEYS[key]) parsed[key] = getConsentStateForCategory(parsed[key]);
232    });
233    // Backward compat: accept old "advertisement" key as alias for "marketing".
234    if (!parsed.marketing && parsed.advertisement) {
235        parsed.marketing = parsed.advertisement;
236    }
237    // Require only `necessary` — the one category guaranteed on every install.
238    // Other categories (analytics, marketing, functional, performance, or any
239    // custom slug) are optional; absent ones default to "denied" downstream in
240    // buildConsentState(). Hard-requiring a fixed slug list rejected the cookie
241    // on installs that renamed/replaced a default category (e.g. "performance").
242    if (parsed.necessary !== "granted" && parsed.necessary !== "denied") {
243        return null;
244    }
245    return parsed;
246}
247
248// Read a category's consent state, defaulting absent categories to "denied".
249function fazCat(cookieObj, slug) {
250    return cookieObj && cookieObj[slug] === "granted" ? "granted" : "denied";
251}
252
253function buildConsentState(cookieObj) {
254    var marketing = fazCat(cookieObj, "marketing");
255    // analytics_storage is granted when EITHER the "analytics" OR the
256    // "performance" category is granted (performance is a valid analytics-class
257    // slug on some installs); previously "performance" was dropped entirely.
258    var analytics =
259        fazCat(cookieObj, "analytics") === "granted" || fazCat(cookieObj, "performance") === "granted"
260            ? "granted"
261            : "denied";
262
263    // ADVANCED CONSENT MODE ONLY: the `analytics` category decides on its own.
264    //
265    // In Basic mode the granted-wins merge above is right. `performance` is an
266    // analytics-class category, so granting it is a consent to analytics-class
267    // storage, and the tags belonging to `analytics` are hard-blocked by the
268    // script gate regardless of what this signal says — the signal cannot let
269    // anything through.
270    //
271    // Advanced mode removes exactly that backstop: Consent-Mode-aware Google
272    // tags (gtag.js / GA4 / Ads) are deliberately allowed to load
273    // (class-frontend.php, is_gcm_managed_script) so they can send modeled
274    // pings. GA4 is classified `analytics`. So a visitor who denied Analytics
275    // and granted Performance had GA4 loaded AND told analytics_storage was
276    // granted, and it wrote its cookies against that denial — the signal became
277    // the only control, and it was pointing the wrong way.
278    //
279    // Deliberately keyed on the `analytics` category rather than made
280    // most-restrictive: the exempted tags are Google's own and that is the
281    // category they belong to, so an install that offers only `performance`
282    // keeps working (analytics absent -> the merge above still decides), while
283    // one that offers both honours the decision made about the tag actually
284    // running.
285    if (data.advanced_mode) {
286        var analyticsRaw = cookieObj ? cookieObj.analytics : undefined;
287        if ("granted" === analyticsRaw || "denied" === analyticsRaw) {
288            analytics = analyticsRaw;
289        }
290    }
291    // Non-personalized ads fallback: when enabled and marketing is denied, we
292    // do NOT grant ad_storage (that would set ad cookies without consent —
293    // unlawful in EEA/UK/CH). ad_storage stays "denied"; Consent Mode v2 serves
294    // non-personalized, cookieless ads in that state. For legacy ad tags that
295    // don't read Consent Mode we signal `npa` (two-sided: set to 0 when
296    // marketing is later granted so it self-clears within the session).
297    setNpaIfDenied(marketing);
298    return {
299        ad_storage: marketing,
300        analytics_storage: analytics,
301        functionality_storage: fazCat(cookieObj, "functional"),
302        personalization_storage: fazCat(cookieObj, "functional"),
303        security_storage: fazCat(cookieObj, "necessary"),
304        ad_user_data: marketing,
305        ad_personalization: marketing,
306    };
307}
308
309function updateConsentState(consentState) {
310    gtag("consent", "update", consentState);
311}
312
313// NOTE: the baseline `consent default` (region / denied) has already been
314// emitted above, and a returning visitor's stored grants were restored via
315// `consent update`. We only need to handle live consent changes below.
316
317// Re-apply on consent changes (banner interaction).
318document.addEventListener("fazcookie_consent_update", function () {
319    var updated = parseConsentCookie();
320    if (!updated) {
321        // parseConsentCookie() returns null when the cookie is stale (server
322        // bumped consent_revision since it was written) or malformed. In that
323        // window there is nothing actionable to push to gtag: leave the
324        // previous consent state untouched and skip GACM too, otherwise we
325        // would clobber the live provider list with "1~" (empty).
326        return;
327    }
328    updateConsentState(buildConsentState(updated));
329    // Also update GACM additional consent string if enabled.
330    if (data.gacm_enabled && data.gacm_provider_ids) {
331        setAdditionalConsent(updated);
332    }
333});
334
335// Google Additional Consent Mode (GACM).
336// The Additional Consent string format: "1~id.id.id..."
337// Version 1 + tilde + dot-separated ATP IDs the user consented to.
338function setAdditionalConsent(consentObj) {
339    if (!data.gacm_enabled) return;
340    var providerRaw = data.gacm_provider_ids;
341    var providerStr = typeof providerRaw === "string" ? providerRaw.trim() : "";
342    if (!providerStr) return;
343
344    // Only include provider IDs when marketing consent is granted.
345    var adsGranted = consentObj && consentObj.marketing === "granted";
346    var acString;
347    if (adsGranted) {
348        // Include all configured provider IDs.
349        acString = "1~" + providerStr.split(/[,\s]+/).filter(Boolean).join(".");
350    } else {
351        // No consent - empty provider list.
352        acString = "1~";
353    }
354
355    gtag("set", "addtl_consent", acString);
356}
357
358// Apply GACM on page load if enabled.
359if (data.gacm_enabled && data.gacm_provider_ids) {
360    setAdditionalConsent(initialCookieObj);
361}
362
363})();

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.