PageSourceSearch

https://w3b.ee/wp-content/plugins/albacross/assets/js/albacross-lo…&client_id=89115790&plugin_version=1.6.3

js w3b.ee collected 2026-10-10 00:33:48 UTC 8,913 bytes, 304 lines download raw bytes

1/**
2 * Albacross first-party loader.
3 */
4(function (window, document) {
5    'use strict';
6
7    var TRACKER_SRC = 'https://serve.albacross.com/track.js';
8    var SOURCE_NAME = 'WordPress-Plugin';
9    var LOADER_NAME = 'albacross-loader';
10
11    /* Attributes a delay-JavaScript engine may move the real src into. */
12    var SRC_ATTRIBUTES = ['src', 'data-rocket-src', 'data-src'];
13
14    /* Opt-out markers understood by the common optimizers, copied onto the
15     * injected tracker so it is not delayed, deferred or combined either. */
16    var OPT_OUT_ATTRIBUTES = [
17        ['data-cfasync', 'false'],
18        ['data-nowprocket', '1'],
19        ['data-no-optimize', '1'],
20        ['data-noptimize', '1'],
21        ['data-no-defer', '1'],
22        ['data-jetpack-boost', 'ignore'],
23        ['data-pagespeed-no-defer', '1']
24    ];
25
26    /**
27     * Log a message without ever throwing.
28     *
29     * @param {string} message Message to log.
30     */
31    function warn(message) {
32        if (window.console && typeof window.console.warn === 'function') {
33            window.console.warn('Albacross: ' + message);
34        }
35    }
36
37    /**
38     * Apply the same rules as albacross_sanitize_client_id() in PHP.
39     *
40     * @param {*} value Raw value.
41     * @return {string} Sanitized Client ID, possibly empty.
42     */
43    function sanitizeClientId(value) {
44        if (typeof value !== 'string' && typeof value !== 'number') {
45            return '';
46        }
47
48        return String(value).replace(/[^A-Za-z0-9_-]/g, '').substring(0, 64);
49    }
50
51    /**
52     * Read an attribute without throwing on non-elements.
53     *
54     * @param {Element} tag  Element to read from.
55     * @param {string}  name Attribute name.
56     * @return {string} Attribute value, or an empty string.
57     */
58    function attr(tag, name) {
59        if (!tag || typeof tag.getAttribute !== 'function') {
60            return '';
61        }
62
63        return tag.getAttribute(name) || '';
64    }
65
66    /**
67     * Read a query argument out of a URL.
68     *
69     * Hand-parsed rather than using URL and URLSearchParams, which are not
70     * available in every browser this plugin still supports.
71     *
72     * @param {string} url  URL to read.
73     * @param {string} name Argument name.
74     * @return {string} Decoded value, or an empty string.
75     */
76    function queryArg(url, name) {
77        if (!url) {
78            return '';
79        }
80
81        var match = new RegExp('[?&]' + name + '=([^&#]*)').exec(url);
82
83        if (!match) {
84            return '';
85        }
86
87        try {
88            return decodeURIComponent(match[1].replace(/\+/g, ' '));
89        } catch (e) {
90            return match[1];
91        }
92    }
93
94    /**
95     * Collect the elements that may be this loader's own script tag, in
96     * descending order of confidence.
97     *
98     * @return {Element[]} Candidate elements, without duplicates.
99     */
100    function candidateTags() {
101        var selector = [];
102        var candidates = [];
103        var found;
104        var i;
105
106        for (i = 0; i < SRC_ATTRIBUTES.length; i++) {
107            selector.push('script[' + SRC_ATTRIBUTES[i] + '*="' + LOADER_NAME + '"]');
108        }
109
110        found = [
111            document.currentScript,
112            document.getElementById('albacross-tracker-js'),
113            document.querySelector('[data-albacross-client-id]'),
114            document.querySelector(selector.join(','))
115        ];
116
117        for (i = 0; i < found.length; i++) {
118            if (found[i] && -1 === indexOf(candidates, found[i])) {
119                candidates.push(found[i]);
120            }
121        }
122
123        return candidates;
124    }
125
126    /**
127     * Array.prototype.indexOf for the elements collected above.
128     *
129     * @param {Array} list  List to search.
130     * @param {*}     value Value to look for.
131     * @return {number} Index, or -1.
132     */
133    function indexOf(list, value) {
134        for (var i = 0; i < list.length; i++) {
135            if (list[i] === value) {
136                return i;
137            }
138        }
139
140        return -1;
141    }
142
143    /**
144     * Read a query argument from whichever src attribute survived.
145     *
146     * @param {Element} tag  Candidate script tag.
147     * @param {string}  name Argument name.
148     * @return {string} Value, or an empty string.
149     */
150    function queryArgFromTag(tag, name) {
151        for (var i = 0; i < SRC_ATTRIBUTES.length; i++) {
152            var value = queryArg(attr(tag, SRC_ATTRIBUTES[i]), name);
153
154            if (value) {
155                return value;
156            }
157        }
158
159        return '';
160    }
161
162    /**
163     * Resolve the Client ID from the first channel that survived.
164     *
165     * @param {Element[]} tags Candidate script tags.
166     * @return {string} Sanitized Client ID, or an empty string.
167     */
168    function resolveClientId(tags) {
169        var clientId = sanitizeClientId(window._nQc);
170        var i;
171
172        if (clientId) {
173            return clientId;
174        }
175
176        for (i = 0; i < tags.length; i++) {
177            clientId = sanitizeClientId(attr(tags[i], 'data-albacross-client-id'));
178
179            if (clientId) {
180                return clientId;
181            }
182        }
183
184        for (i = 0; i < tags.length; i++) {
185            clientId = sanitizeClientId(queryArgFromTag(tags[i], 'client_id'));
186
187            if (clientId) {
188                return clientId;
189            }
190        }
191
192        return '';
193    }
194
195    /**
196     * Resolve the plugin version. Informational only, so failure is fine.
197     *
198     * @param {Element[]} tags Candidate script tags.
199     * @return {string} Version string, or an empty string.
200     */
201    function resolveVersion(tags) {
202        var version = typeof window._nQsv === 'string' ? window._nQsv : '';
203        var i;
204
205        for (i = 0; !version && i < tags.length; i++) {
206            version = attr(tags[i], 'data-albacross-version') ||
207                queryArgFromTag(tags[i], 'plugin_version');
208        }
209
210        return version;
211    }
212
213    /**
214     * Whether the tracker is already present in the document.
215     *
216     * Covers the inline snippet used before 1.6.0, a tag added through a tag
217     * manager, and a second copy of this loader.
218     *
219     * @return {boolean} True when track.js is already on the page.
220     */
221    function trackerPresent() {
222        /* track.js sets this itself once it has initialized. */
223        if (window._nQ_scriptLoaded) {
224            return true;
225        }
226
227        var scripts = document.getElementsByTagName('script');
228
229        for (var i = 0; i < scripts.length; i++) {
230            for (var j = 0; j < SRC_ATTRIBUTES.length; j++) {
231                if (-1 !== attr(scripts[i], SRC_ATTRIBUTES[j]).indexOf('serve.albacross.com/track.js')) {
232                    return true;
233                }
234            }
235        }
236
237        return false;
238    }
239
240    /* Guard against this file executing more than once.
241     *
242     * The flag has a name of its own on purpose. window._nQ_scriptLoaded
243     * belongs to track.js, which uses it as its re-entry guard: track.js only
244     * sets its cookies and starts sending events when _nQc is set and
245     * _nQ_scriptLoaded is not. Setting it here would leave track.js loaded but
246     * inert, which is what 1.6.2 did. This file must only ever read it. */
247    if (window._nQ_wpLoaderRan) {
248        return;
249    }
250
251    window._nQ_wpLoaderRan = true;
252
253    var tags = candidateTags();
254    var clientId = resolveClientId(tags);
255
256    if (!clientId) {
257        warn(
258            'no Client ID found. The tracking script was not loaded. Check that ' +
259            'the Client ID is saved in the plugin settings, and that your ' +
260            'optimization plugin or CDN is not stripping inline scripts, data ' +
261            'attributes and query strings from ' + LOADER_NAME + '.js.'
262        );
263
264        return;
265    }
266
267    window._nQc = clientId;
268    window._nQs = SOURCE_NAME;
269    window._nQsv = resolveVersion(tags);
270
271    if (trackerPresent()) {
272        return;
273    }
274
275    var tracker = document.createElement('script');
276
277    tracker.async = true;
278    tracker.src = TRACKER_SRC;
279
280    for (var i = 0; i < OPT_OUT_ATTRIBUTES.length; i++) {
281        tracker.setAttribute(OPT_OUT_ATTRIBUTES[i][0], OPT_OUT_ATTRIBUTES[i][1]);
282    }
283
284    /* Carry the page's Content Security Policy nonce over, when there is one. */
285    for (var n = 0; n < tags.length; n++) {
286        var nonce = tags[n].nonce || attr(tags[n], 'nonce');
287
288        if (nonce) {
289            tracker.setAttribute('nonce', nonce);
290            tracker.nonce = nonce;
291            break;
292        }
293    }
294
295    tracker.onerror = function () {
296        warn(
297            'could not load ' + TRACKER_SRC + '. This is usually a consent tool ' +
298            'that has not granted permission yet, a Content Security Policy, or ' +
299            'a tracking blocker in the visitor\'s browser.'
300        );
301    };
302
303    (document.head || document.documentElement).appendChild(tracker);
304}(window, document));

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.