1/* 2 3--- 4 5MIT License 6 7Copyright (c) Conva Ventures Inc 8 9Permission is hereby granted, free of charge, to any person obtaining a copy 10of this software and associated documentation files (the "Software"), to deal 11in the Software without restriction, including without limitation the rights 12to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13copies of the Software, and to permit persons to whom the Software is 14furnished to do so, subject to the following conditions: 15 16The above copyright notice and this permission notice shall be included in all 17copies or substantial portions of the Software. 18 19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25SOFTWARE. 26 27*/ 28 29(function () { 30 "use strict"; 31 32 let queue = (window.raqeeb && window.raqeeb.q) || []; 33 let config = { 34 siteId: "", 35 trackerUrl: "", 36 }; 37 const commands = { 38 set: set, 39 trackPageview: trackPageview, 40 setTrackerUrl: setTrackerUrl, 41 }; 42 43 function set(key, value) { 44 config[key] = value; 45 } 46 47 function setTrackerUrl(value) { 48 return set("trackerUrl", value); 49 } 50 51 // convert object to query string 52 function stringifyObject(obj) { 53 var keys = Object.keys(obj); 54 55 return ( 56 "?" + 57 keys 58 .map(function (k) { 59 return ( 60 encodeURIComponent(k) + "=" + encodeURIComponent(obj[k]) 61 ); 62 }) 63 .join("&") 64 ); 65 } 66 67 function getCookie(name) { 68 var cookies = document.cookie ? document.cookie.split("; ") : []; 69 70 for (var i = 0; i < cookies.length; i++) { 71 var parts = cookies[i].split("="); 72 if (decodeURIComponent(parts[0]) !== name) { 73 continue; 74 } 75 76 var cookie = parts.slice(1).join("="); 77 return decodeURIComponent(cookie); 78 } 79 80 return ""; 81 } 82 83 function setCookie(name, data, args) { 84 name = encodeURIComponent(name); 85 data = encodeURIComponent(String(data)); 86 87 var str = name + "=" + data; 88 89 if (args.path) { 90 str += ";path=" + args.path; 91 } 92 if (args.expires) { 93 str += ";expires=" + args.expires.toUTCString(); 94 } 95 96 document.cookie = str + ";SameSite=None;Secure"; 97 } 98 99 function newVisitorData() { 100 return { 101 isNewVisitor: true, 102 isNewSession: true, 103 pagesViewed: [], 104 previousPageviewId: "", 105 lastSeen: +new Date(), 106 }; 107 } 108 109 function getData() { 110 let thirtyMinsAgo = new Date(); 111 thirtyMinsAgo.setMinutes(thirtyMinsAgo.getMinutes() - 30); 112 113 let data = getCookie("_raqeeb"); 114 if (!data) { 115 return newVisitorData(); 116 } 117 118 try { 119 data = JSON.parse(data); 120 } catch (e) { 121 console.error(e); 122 return newVisitorData(); 123 } 124 125 if (data.lastSeen < +thirtyMinsAgo) { 126 data.isNewSession = true; 127 } 128 129 return data; 130 } 131 132 function getLpData() { 133 let thirtyMinsAgo = new Date(); 134 thirtyMinsAgo.setMinutes(thirtyMinsAgo.getMinutes() - 30); 135 136 let data = getCookie("_raqeeblp"); 137 if (!data) { 138 return newVisitorData(); 139 } 140 141 try { 142 data = JSON.parse(data); 143 } catch (e) { 144 console.error(e); 145 return newVisitorData(); 146 } 147 148 if (data.lastSeen < +thirtyMinsAgo) { 149 data.isNewSession = true; 150 } 151 152 return data; 153 } 154 function extractLandingPagePath(path) { 155 const match = path.match(/^\/l\/[a-z0-9]+(?:-[a-z0-9]+)*/); 156 return match ? match[0] : path; 157 } 158 159 function findTrackerUrl() { 160 const el = document.getElementById("raqeeb-script"); 161 return el ? el.src.replace("tracker.js", "collect") : ""; 162 } 163 164 function trackPageview(vars) { 165 vars = vars || {}; 166 167 // ignore prerendered pages 168 if ( 169 "visibilityState" in document && 170 document.visibilityState === "prerender" 171 ) { 172 return; 173 } 174 175 // if <body> did not load yet, try again at dom ready event 176 if (document.body === null) { 177 document.addEventListener("DOMContentLoaded", () => { 178 trackPageview(vars); 179 }); 180 return; 181 } 182 183 // parse request, use canonical if there is one 184 let req = window.location; 185 186 // do not track if not served over HTTP or HTTPS (eg from local filesystem) and we're not in an Electron app 187 if (req.host === "" && navigator.userAgent.indexOf("Electron") < 0) { 188 return; 189 } 190 191 // find canonical URL 192 let canonical = document.querySelector('link[rel="canonical"][href]'); 193 if (canonical) { 194 let a = document.createElement("a"); 195 a.href = canonical.href; 196 197 // use parsed canonical as location object 198 req = a; 199 } 200 201 let path = vars.path || req.pathname + req.search; 202 if (!path) { 203 path = "/"; 204 } 205 206 // determine hostname 207 let hostname = vars.hostname || req.protocol + "//" + req.hostname; 208 209 // only set referrer if not internal 210 let referrer = vars.referrer || ""; 211 if (document.referrer.indexOf(hostname) < 0) { 212 referrer = document.referrer; 213 } 214 if (referrer && referrer.endsWith('/')) { 215 referrer = referrer.slice(0, -1); 216 } 217 218 let data = getData(); 219 const d = { 220 pid: data.previousPageviewId || "", 221 p: path, 222 h: hostname, 223 r: referrer, 224 u: data.pagesViewed.indexOf(path) == -1 ? 1 : 0, 225 nv: data.isNewVisitor ? 1 : 0, 226 ns: data.isNewSession ? 1 : 0, 227 sid: config.siteId, 228 }; 229 230 let url = config.trackerUrl || findTrackerUrl(); 231 let img = document.createElement("img"); 232 img.setAttribute("alt", ""); 233 img.setAttribute("aria-hidden", "true"); 234 img.setAttribute("style", "position:absolute"); 235 img.src = url + stringifyObject(d); 236 img.addEventListener("load", function () { 237 let midnight = new Date(); 238 midnight.setHours(24); 239 midnight.setMinutes(0); 240 midnight.setSeconds(0); 241 242 // update data in cookie 243 if (data.pagesViewed.indexOf(path) == -1) { 244 data.pagesViewed.push(path); 245 } 246 data.previousPageviewId = d.id; 247 data.isNewVisitor = false;
248 data.isNewSession = false; 249 data.lastSeen = +new Date(); 250 setCookie("_raqeeb", JSON.stringify(data), { 251 expires: midnight, 252 path: "/", 253 }); 254 255 // remove tracking img from DOM 256 document.body.removeChild(img); 257 }); 258 259 // in case img.onload never fires, remove img after 1s & reset src attribute to cancel request 260 window.setTimeout(() => { 261 if (!img.parentNode) { 262 return; 263 } 264 265 img.src = ""; 266 document.body.removeChild(img); 267 }, 1000); 268 269 // add to DOM to fire request 270 document.body.appendChild(img); 271 272 // for landing pages only 273 let isLandingPage = path.startsWith("/l/"); 274 275 if(isLandingPage) { 276 let dataLp = getLpData(); 277 let lpPath=extractLandingPagePath(path) 278 const dlp = { 279 pid: dataLp.previousPageviewId || "", 280 p: lpPath, 281 h: hostname, 282 r: referrer, 283 u: dataLp.pagesViewed.indexOf(lpPath) == -1 ? 1 : 0, 284 nv: dataLp ? 1 : 0, 285 ns: dataLp.isNewSession ? 1 : 0, 286 sid: config.siteId + lpPath, 287 }; 288 289 let imgLp = document.createElement("img"); 290 imgLp.setAttribute("alt", ""); 291 imgLp.setAttribute("aria-hidden", "true"); 292 imgLp.setAttribute("style", "position:absolute"); 293 imgLp.src = url + stringifyObject(dlp); 294 imgLp.addEventListener("load", function() { 295 let midnight = new Date(); 296 midnight.setHours(24); 297 midnight.setMinutes(0); 298 midnight.setSeconds(0); 299 300 // update data in cookie 301 if (dataLp.pagesViewed.indexOf(lpPath) == -1) { 302 dataLp.pagesViewed.push(lpPath); 303 } 304 dataLp.previousPageviewId = dlp.id; 305 dataLp.isNewVisitor = false; 306 dataLp.isNewSession = false; 307 dataLp.lastSeen = +new Date(); 308 setCookie("_raqeeblp", JSON.stringify(dataLp), { 309 expires: midnight, 310 path: "/", 311 }); 312 313 // remove tracking img from DOM 314 document.body.removeChild(imgLp); 315 }); 316 317 window.setTimeout(() => { 318 if (!imgLp.parentNode) { 319 return; 320 } 321 322 imgLp.src = ""; 323 document.body.removeChild(imgLp); 324 }, 1000); 325 326 // add to DOM to fire request 327 document.body.appendChild(imgLp); 328 } 329 } 330 331 // override global raqeeb object 332 window.raqeeb = function () { 333 var args = [].slice.call(arguments); 334 var c = args.shift(); 335 commands[c].apply(this, args); 336 }; 337 338 window.raqeeb.trackPageview = trackPageview; 339 340 // process existing queue 341 queue.forEach((i) => raqeeb.apply(this, i)); 342})();
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.