1/*! 2 * MrBlue GA4 wrapper 3 */ 4(function (window, document) { 5 if (window.mrblueGa4) { 6 return; 7 } 8 9 function toArray(args) { 10 return Array.prototype.slice.call(args || []); 11 } 12 13 function toJson(value) { 14 try { 15 return JSON.stringify(value); 16 } catch (e) { 17 return JSON.stringify({ 18 stringifyError: e.message 19 }); 20 } 21 } 22 23 function getErrorInfo(error) { 24 if (!error) { 25 return {}; 26 } 27 28 return { 29 name: error.name || "", 30 message: error.message || String(error), 31 stack: error.stack || "" 32 }; 33 } 34 35 function getRefreshToken(callback) { 36 var tokenInput = document.getElementById("__RequestVerificationToken"); 37 if (tokenInput && tokenInput.value) { 38 callback(tokenInput.value); 39 return; 40 } 41 42 if (!window.XMLHttpRequest) { 43 callback(""); 44 return; 45 } 46 47 var xhr = new XMLHttpRequest(); 48 xhr.open("GET", "/shared/refreshtoken", true); 49 xhr.onreadystatechange = function () { 50 if (xhr.readyState !== 4) { 51 return; 52 } 53 54 if (xhr.status < 200 || xhr.status >= 300) { 55 callback(""); 56 return; 57 } 58 59 var container = document.createElement("div"); 60 container.innerHTML = xhr.responseText; 61 var inputs = container.getElementsByTagName("input"); 62 var input = null; 63 for (var i = 0; i < inputs.length; i += 1) { 64 if (inputs[i].type === "hidden") { 65 input = inputs[i]; 66 break; 67 } 68 } 69 callback(input ? input.value : ""); 70 }; 71 xhr.send(); 72 } 73 74 function postLog(action, param) { 75 if (typeof window.mrblueAjax === "function") { 76 window.mrblueAjax("/shared/_loguseractionwithparam", "post", { 77 action: action, 78 param: param 79 }, function () { 80 }); 81 return; 82 } 83 84 if (!window.XMLHttpRequest) { 85 return; 86 } 87 88 getRefreshToken(function (token) { 89 if (!token) { 90 return; 91 } 92 93 var xhr = new XMLHttpRequest(); 94 xhr.open("POST", "/shared/_loguseractionwithparam", true); 95 xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); 96 xhr.setRequestHeader("X-CSRF-TOKEN", token); 97 xhr.send("action=" + encodeURIComponent(action) + "¶m=" + encodeURIComponent(param)); 98 }); 99 } 100 101 function logFailure(functionName, args, error) { 102 try { 103 postLog("GA4 event send failed", toJson({ 104 functionName: functionName, 105 arguments: args, 106 error: getErrorInfo(error), 107 url: window.location.href 108 })); 109 } catch (e) { 110 } 111 } 112 113 function callGa4(functionName, args) { 114 var callArgs = toArray(args); 115 116 try { 117 var ga4Function = window[functionName]; 118 if (typeof ga4Function !== "function") { 119 throw new Error(functionName + " is not a function"); 120 } 121 122 return ga4Function.apply(window, callArgs); 123 } catch (error) { 124 logFailure(functionName, callArgs, error); 125 return undefined; 126 } 127 } 128 129 window.mrblueGa4 = { 130 page: function () { 131 return callGa4("sendGAPage", arguments); 132 }, 133 virtualPage: function () { 134 return callGa4("sendGAVirPage", arguments); 135 }, 136 event: function () { 137 return callGa4("sendGAEvent", arguments); 138 }, 139 ecommerce: function () { 140 return callGa4("sendGAEcommerce", arguments); 141 } 142 }; 143})(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.