www-google-analytics-com_analytics.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. (function () {
  2. 'use strict';
  3. // https://developers.google.com/analytics/devguides/collection/analyticsjs/
  4. const noopfn = function () {
  5. };
  6. //
  7. const Tracker = function () {
  8. };
  9. const p = Tracker.prototype;
  10. p.get = noopfn;
  11. p.set = noopfn;
  12. p.send = noopfn;
  13. //
  14. const w = window;
  15. const gaName = w.GoogleAnalyticsObject || 'ga';
  16. const gaQueue = w[gaName];
  17. const ga = function (...args) {
  18. const len = args.length;
  19. if (len === 0) { return; }
  20. let fn;
  21. const a = args[len - 1];
  22. if (typeof a === 'object' && typeof a.hitCallback === 'function') {
  23. fn = a.hitCallback;
  24. } else if (typeof a === 'function') {
  25. fn = () => { a(ga.create()); };
  26. } else {
  27. const pos = args.indexOf('hitCallback');
  28. if (pos !== -1 && typeof args[pos + 1] === 'function') {
  29. fn = args[pos + 1];
  30. }
  31. }
  32. if (typeof fn !== 'function') { return; }
  33. try {
  34. fn();
  35. } catch {
  36. }
  37. };
  38. ga.create = function () {
  39. return new Tracker();
  40. };
  41. ga.getByName = function () {
  42. return new Tracker();
  43. };
  44. ga.getAll = function () {
  45. return [new Tracker()];
  46. };
  47. ga.remove = noopfn;
  48. // https://github.com/uBlockOrigin/uAssets/issues/2107
  49. ga.loaded = true;
  50. w[gaName] = ga;
  51. // https://github.com/gorhill/uBlock/issues/3075
  52. const dl = w.dataLayer;
  53. if (typeof dl === 'object') {
  54. if (typeof dl.hide === 'object' && typeof dl.hide.end === 'function') {
  55. dl.hide.end();
  56. dl.hide.end = () => { };
  57. }
  58. if (typeof dl.push === 'function') {
  59. const doCallback = function (item) {
  60. if (typeof item === 'object' === false) { return; }
  61. if (typeof item.eventCallback !== 'function') { return; }
  62. // eslint-disable-next-line sukka/prefer-timer-id -- deliberate use of setTimeout
  63. setTimeout(item.eventCallback, 1);
  64. item.eventCallback = () => { };
  65. };
  66. dl.push = new Proxy(dl.push, {
  67. apply(target, thisArg, args) {
  68. doCallback(args[0]);
  69. return Reflect.apply(target, thisArg, args);
  70. }
  71. });
  72. if (Array.isArray(dl)) {
  73. const q = dl.slice();
  74. for (const item of q) {
  75. doCallback(item);
  76. }
  77. }
  78. }
  79. }
  80. // empty ga queue
  81. if (typeof gaQueue === 'function' && Array.isArray(gaQueue.q)) {
  82. const q = gaQueue.q.slice();
  83. gaQueue.q.length = 0;
  84. for (const entry of q) {
  85. ga(...entry);
  86. }
  87. }
  88. }());