Skip to content

Instantly share code, notes, and snippets.

@hexalys

hexalys/tag.js Secret

Created September 2, 2023 03:30
Show Gist options
  • Save hexalys/9ede789cc553042c4389a810e1952286 to your computer and use it in GitHub Desktop.
Save hexalys/9ede789cc553042c4389a810e1952286 to your computer and use it in GitHub Desktop.
tag.js Snippet (Analytics Tracking Script with GA4 Enhanced Measurements w/gtag functionality)
!(function(r, f, e, o, k) {
if (!((typeof module === o && module[e] && f(e)) || typeof define === 'function' && define.amd && !define([], f))) {
(typeof e === o ? e : r)[k] = f(e)[k]
}
}(this, ((E, o, f, k) => ((D, O, G, J, S, X, M, V, C, _, x, y, z) => {
'use strict';
const W = typeof window !== V ? window : typeof global === k ? global : self,
N = navigator,
e = {
0: (e, t) => {
let J = 0,
H, R;
const L = localStorage,
I = Date.now,
A = [
[I()]
],
_ = (e = null, k, r, o = 'object', b = 'boolean', n = 'number') => {
const t = (a, e) => {
const i = a.length - 1,
[, t] = a[i];
e ? t && a.push([I()]) : t || a[i].push(I())
};
return k && k != !0 && r !== !1 ? (!e && e !== 0) ? r : (k.length === 1 ? (typeof e === (k === 'o' ? o : (k === 's' ? 'string' : (k === 'n' ? n : b))) ? e : r) : ((r && !(k in e) && (o = r)) || (b = typeof e[k] === b) || (n = typeof e[k] === n) || (o = e[k])) && ((o = b | n ? e[k] * 1 : o.trim()) || o === 0) && (r || delete e[k]) && (o >= 0 ? (r === '' ? o + r : o * 1) : o)) : e !== null ? (e > 0 ? (typeof k === b ? t(A[e], k) || (r ? _(e) : k) : A[e] ? A[e].reduce(((e, [t, n = I()]) => e + (n - t)), 0) + '' : 0) : O.keys(e).map((t => (z.includes(t) || x.includes(t) || (t in X && t.replace(X[t], x[4])) || t.includes('.') || t.slice(-1) >= 0) ? [t, e[t]] : [((_(r = e[t], 'n') || r >= 0) ? 'epn.' : 'ep.') + (k ? k + t : t), r === V ? V : (k && r === '' ? '' : (r + '').trim())]))) : (A[++J] = [
[I()]
],
J)
},
i = (k, n) => {
const c = _(k, 'n'),
t = () => ~~((n || I()) / 1e3 + (c ? k : 0));
return (c || (!k || _(n, 'n') >= 0)) ? t() : n.length > 16 ? n : ~~(Math.random() * 2147483648) + (k ? '.' + (n > 0 ? n : t()) : '')
},
g = (k, n) => S[k] || L[k] || (L[k] = i(k, n)),
s = (k, n) => {
const c = S.sc || L[C.sc] || 0,
p = c * 1 + (!c || i(-60 * C.sl) > ((n || S).st || L[C.si])),
t = p > c && !k ? L[C.si] = i(0) : S.si || L[C.si] || 0;
return {
s: (p > c) * 1,
e: L[C.se] = p > c ? 0 : L[C.se],
c: L[C.sc] = p,
si: n = t || g(C.si, (k || 0) * 1),
ci: g(C.ci, (n || 0) + ''),
st: L[C.st] = i(0),
f: !c * 1
}
},
u = (k, n) => {
const c = 'hostname',
l = D.location,
{
[c]: d,
href: h,
pathname: u,
origin: o,
protocol: p,
search: s,
searchParams: f
} = new URL(k ? (k[0] === '/' ? l.origin + k : k) : l.href),
r = s => s.replace(new RegExp(`(&|\\?)(${C.pi})=[^&]+`), '');
k = o + u + s;
H = n && R && R !== k;
k = {
l: r(_(n, y[3]) || k),
h: h,
o: o,
d: d,
u: u,
p: p + '//',
r: n ? r(n[y[4]] || (H ? R : D.referrer)) : V,
t: _(n, y[5], D.title),
a: s,
f: f,
e: (d !== l[c]) * 1,
s: p[4] === 's'
};
n && (R = k.l);
return k
};
M(t, {
d: () => (e, t = 300, n = 0) => (...o) => (clearTimeout(n),
n = setTimeout(e, t, ...o)),
p: () => (e, t) => ((t = ~~(100 * Math.abs(e.scrollTop / (e.scrollHeight - e.clientHeight)))) >= 0) ? t : 100,
l: () => (e, t) => t ? L[e] = t : L[e],
c: () => (e, t) => ((e = (D.cookie.match('(^|;)' + e + '=([^;]*)') || 0)[2]) && t ? e.slice(t) : e) || '',
_: () => _,
i: () => i,
g: () => g,
s: () => s,
u: () => u
})
},
1: (e, t) => {
_(t, 'M', v),
C = t.c = {
tn: X,
ci: X + 'cid',
si: X + 'sid',
sc: X + 'sct',
st: X + 'set',
se: X + 'seg',
tu: 'www.google-analytics.com/g/collect',
sl: 30,
et: 10 * 1e3,
pi: 'email|phone|password',
mp: [10, 25, 50, 75],
sp: [10, 50, 90],
sq: ['q', 's'],
fi: '',
re: '',
};
t.p = {
send_page_view: !0,
transport_url: 'tu',
language: 'ul',
page_location: 'dl',
page_referrer: 'dr',
page_title: 'dt',
ignore_referrer: 'ir',
currency: 'cu',
client_id: 'cid',
user_id: 'uid',
traffic_type: 'tt',
conversion: '_c',
debug_mode: '_dbg',
allow_google_signals: 'ngs',
cookie_name: '_ga',
};
t.i = {
m_id: 'id',
m_name: 'nm',
t_id: 'li',
t_name: 'ln',
n_id: 'pi',
n_name: 'pn',
e_name: 'cn',
e_slot: 'cs',
ion: 'af',
pon: 'cp',
nt: 'ds',
ex: 'lp',
and: 'br',
ry: 'ca',
y2: 'c2',
y3: 'c3',
y4: 'c4',
y5: 'c5',
ant: 'va',
n_id: 'lo',
ce: 'pr',
ty: 'qt'
};
X = t.k = {
p: '_p',
fv: '_fv',
ss: '_ss',
s: '_s',
et: '_et',
eu: '_eu',
ee: '_ee',
nsi: '_nsi',
en: 'en'
}
}
},
t = {},
v = {
value: !0
},
n = (o, s) => (t[o] ? t[o][E] : e[o](s = t[o] = {
[E]: {}
}, s[E]),
s[E]);
D = W[D];
_ = O.defineProperty;
M = (e, t) => {
f = O.prototype.hasOwnProperty;
_(e, Symbol.toStringTag, {
value: 'Module'
}),
_(e, 'M', v);
for (k in t)
f.call(t, k) && !f.call(e, k) && _(e, k, {
O: !0,
get: t[k]
})
};
return (o => {
const c = ['js', 'set', 'config', 'event'],
$ = 'page_view',
U = {},
u = n(0),
i = n(1),
_ = u._,
M = O.assign,
R = (t, e, o, d, a, l, r, n, v, p, $ = 'purchase', k = 0) => {
const Q = a => new URLSearchParams(a.filter((([, e]) => e === '' || e))),
R = 'sendBeacon',
m = W.screen,
i = _(d, 'n'),
b = E.length;
p = b ? Q(_(e)) : '';
while (k < b) {
p += '\n' + Q(E[k++])
}
E = [];
$ = (n === $ || p.includes($) || P[y[11]] === 1) * 1;
a = [
['v', 2],
['tid', t],
[z[8], P[y[8]] || S.ci],
[z[9], P[y[9]] || V],
[z[10], P[y[10]] || V],
['sid', S.si],
['sct', S.c],
['seg', S.e * 1 || u.l(C.se, $ || (!S.s && (n === v || p.includes(v) || _(I) > C.et)) * 1)],
['uaflv', C.f],
['uap', C.p],
['uamb', C.m + ''],
[z[2], (P[y[2]] || N[y[2]] || '').toLowerCase()],
['sr', m.width + 'x' + m.height],
[z[3], l.l],
[z[4], l.r],
[z[5], l.t],
[z[6], P[y[6]]],
[z[7], P[y[7]]],
[x[8], b ? V : e.en],
].concat(_(o), a, [
[x[0], g.hid],
[x[1], S.f + $],
[x[2], S.s + $],
[x[3], H + ''],
[x[4], b || S.s ? V : e.et],
[x[5], i ? ('AE' + (d > 1 ? 'E' : 'A')) : V],
[x[6], (X && (!i || d !== 0)) * 1],
[x[7], (S.s && X === !1) * 1],
[z[11], $],
[z[12], (P[y[12]] || Z) * 1],
[z[13], P[y[13]] === 0 ? 1 : V]
]);
r = l.p + r.replace('https://', '') + '?' + Q(a);
l.s && N[R] && N[R](r, p) || (o = new XMLHttpRequest(),
o.open('POST', r, !0),
o.send(p))
},
F = (D) => {
const F = [],
l = 'EventListener',
x = 'documentElement',
r = s => s && s.replace(/.*?\[(.*)\].*/, '$1') || V,
q = (k, o, v, e) => !v ? [
[V, V]
] : _(e ? M({
id: r(e.id),
name: r(e.name)
}, o) : o, k + '_', !1),
w = u.d(e => {
if (Y < 90) {
let n = u.p(e.target[x]),
a = C.sp,
l = a.length,
i = -l;
while (l > 0 && n > Y && i < 0 && a[--l]) {
i = Y < a[l] && n >= a[l] ? a[l] : -l
}
if (i > 0) {
T(e.type, {
'percent_scrolled': Y = i
}, Y >= 90 ? 1 : 0)
}
}
}),
d = u.d(e => (D.dispatchEvent(new Event('sessiontimeout')) && delete G[y[9]]) || (S.st = u.i(0))),
i = e => {
let t = e.type[0];
(t === 'm' && (t = e.type[5] === 'o')) || _(I, t = t === 'f' || t === 'v' && D.visibilityState[0] === t);
(t && u.l(C.st, u.i(0))) || (S.st = u.i(0));
G[y[9]] && ((t && E && clearTimeout(E)) || (E = d()))
},
o = e => {
W.dispatchEvent(new CustomEvent('beforehide', {
detail: (e ? 'out' : 'in') + 'bound'
}))
},
f = e => {
let t = _(e.target, 'o'),
f = ('form' in t && t.form) || t.elements && t;
if (f) {
const s = e.type === 'submit',
a = f ? f.action : V,
i = f ? [].indexOf.call(D.forms, f) + 1 : 0,
p = [].indexOf.call(f, t),
c = f.querySelectorAll('input[type=hidden]').length,
n = f.querySelectorAll('button,input[type]').length - c;
((s && !o(!a.includes(L.o))) || (!F[i] && (F[i] = i))) && T('form_' + (s ? 'submit' : 'start'), [].concat(q('form', {
destination: u.u(a).h,
length: n
}, 1, f), q('first_field', {
type: t.type,
position: p - c
}, t.form, t)), 2)
} else if (P && t.type === 'text' && t.name === 's' && t.value.length > 3) {
T('search', {
'search_term': t.value
})
}
},
c = e => {
let t = _(e.target, 'o');
if (t && !t.form) {
const c = t.classList,
n = 'textContent',
h = t.getAttribute('href'),
f = h && h[0] === '#',
p = c.contains('call') && t[n].replace(/[^\d]/g, ''),
e = c.contains('email') && t[n].toLowerCase(),
a = p || e || (h && !f && (h[0] === 't' || h[0] === 'm')),
d = t.getAttribute('download'),
v = 'type' in t || a,
l = h && u.u(h),
k = l && l.u.slice((l.u.lastIndexOf('.') - 1 >>> 0) + 2),
i = k && (C.fi || 'aspcfmcgiplhtmljsphp').includes(k),
m = k && (C.fi && i || !i);
l && !f && o(l.e);
(v && (a || m || (l && l.e))) && T(m ? 'file_download' : a ? 'launch' : 'click', _({
'method': a ? p ? 'Phone' : 'Email' : V,
'outbound': l ? l.e : V
}).concat(q('link', {
text: t[n],
url: a ? p ? 'tel:+' + p : (e ? 'mailto:' + e : h) : l.l,
domain: a ? V : l.d
}, a, t), q('file', {
name: d ? d.slice(0, d.lastIndexOf('.') + 1) : l ? l.u : V,
extension: k
}, m)), a ? 0 : 1, a ? 0 : V)
}
},
m = e => {
const t = e.type,
m = e.target,
s = m.currentSrc,
v = m.tagName.toLowerCase(),
k = s.slice(s.lastIndexOf('/') + 1, -5),
d = m.duration,
c = m.currentTime,
a = C.mp,
u = t[0] === 't',
n = c / d * 100;
let l = a.length,
i = -l,
p = M[k] || 0;
while (l > 0 && n > p && i < 0 && a[--l]) {
i = p < a[l] && n >= a[l] ? a[l] : -l
}
if (i > 0 || !u) {
l = m.getBoundingClientRect();
e = t[0] === 'p';
if (!(e && p > 0)) {
M[k] = u ? i : (p > 0 ? 100 : 0);
T(v + '_' + (e ? 'start' : (u ? 'progress' : 'complete')), q(v, {
duration: ~~d,
current_time: ~~c || 0,
percent: P[k],
url: s,
provider: '',
title: m.title || V,
visible: (l && l.bottom >= 0 && l.top <= D[x].clientHeight) * 1 + ''
}, !0), 2)
}
}
},
b = u.d((e, t) => {
e[t]('scroll', w),
e[t]('click', c),
e[t]('change', f),
e[t]('submit', f),
e[t]('visibilitychange', i),
C.m || (!e[t](p + 'over', i),
e[t](p + 'leave', i)),
W[t]('blur', i),
W[t]('focus', i),
W[t]('pagehide', (e) => {
T('user_engagement', {}, 0, 1)
})
}, 0),
n = u.d((e, t) => {
P = [];
t = (B ? 'remove' : a) + l;
e.querySelectorAll('audio,video').forEach(n => {
n[t]('play', m),
n[t]('timeupdate', m),
n[t]('ended', m)
})
}, B ? 0 : 600),
v = u.d((e, t) => {
Y = 0;
H || b(D, a + l);
B || n(D);
P || (P = t);
B = 0;
I = _();
T($, {}, H ? 2 : 0);
n(D)
}, 0);
var k, a = 'add',
s = 'state',
p = 'mouse',
h = W.history,
e = {
pushState: 'onpush' + s,
replaceState: 'onreplace' + s
},
P, S = [],
E = 0;
if (G[y[0]]) {
for (k in e) {
let n = k,
f = h[k];
h[k] = (o, t, u) => {
h[e[k]] && h[e[k]]({
[s]: o
}),
v(o, n),
f.apply(h, [o, t, u])
}
}
}
W[a + l]('pageshow', v);
W[a + l]('pop' + s, v)
},
T = (n, o = {}, d, a = [], q) => {
var j = 0,
k = _(d, 's', ''),
l, m, s = '';
I || A(a);
const v = n === $,
r = !v && S.st && u.i(-60 * C.sl) > S.st && (I = _()),
e = I - v * 1,
g = k && k.codePointAt(0) > 96 ? k : 0,
t = k.includes('-') || k > 0 ? {
[k]: !0
} : 0,
x = o[0],
b = a === 0 && J || (!a || !a.length),
D = (t, p, o, d, a, l, x) => {
if (X <= x) {
H++;
s = X ? S = u.s() : S;
for (k in t) {
R(k, p, o, d, a === 1 ? [] : a, l, C.tu, n, $)
}
B = I;
X++;
K = [];
P = []
}
},
T = u.d((...s) => {
D(...s)
}, ((v && (b > 1 && clearTimeout(J))) ? 0 : (X ? 800 : 1200))),
Q = (...s) => {
if (b && K[0]) {
E.push(_(p).concat(v ? [
[z[3], L.h],
[z[4], L.r],
[z[5], L.t]
] : x ? a : _(o)));
b > 1 && (J = T(K))
} else {
(a === 1 && D(...s)) || ((K = O.values({
...s
})) && (J = T(...s)));
v && q && E.push(_({
en: 'view_search_results',
'search_term': q,
et: p.et
}, d))
}
},
p = {
en: n,
et: e > 0 ? Math.round(_(e) / 50) * 50 : V
};
a = x ? o : (!a ? [] : a);
X || (Z = G[y[12]] || d);
for (k in o = M(x ? {} : o, G)) {
i.p[k] && (P[k] = _(o, k))
}
if (l = o.items) {
while (j < l.length) {
for (k in l[j]) {
for (m in i.i) {
k.endsWith(m) && (s += '~' + i.i[m] + l[j][k])
}
}
o['pr' + (++j)] = s
}
delete o.items
}
if (!B ^ K[0]) {
L = u.u(P[z[2]], P);
for (k in C.sq) {
q = q || L.f.get(C.sq[k])
}
}
if (!t && U.length > 1) {
s = 'groups';
for (k in U) {
m = U[k];
((!m[s] && !g || g === 'default') || m[s] && m[s] === g) && (l[k] = m)
}
} else {
if (t) {
(U[t] || (U[t] = {}));
for (k in o = M(o, U[t])) {
k in i.p && (P[k] = _(o, k))
}
}
}
(v && P[y[0]] === 0 && b) || Q(t || U, p, o, d, a, L, X)
},
Q = (e, n, p, d = !1) => {
k = e > -1 ? k : c.indexOf(e);
(k > 2 && !T(n, p = p || {}, _(p, 'send_to') || d)) || (k > 1 && (n in U && M(U, p = (p || {}) && M(U, G)) || (U[n] = (p)))) || (k > 0 && M(G, _(n, 'o', {
[n]: p
})))
},
A = (a, s) => {
a = a.sort((e, t) => c.indexOf(e[0]) - c.indexOf(t[0]));
while (++Y < a.length) {
Q(...a[Y])
}
k = a[0];
s = k ? k[1] : V;
k && k.callee.name,
k !== t && (W[k] = Q),
p = k && k[2];
u.l(C.ci) || (!p || (k = _(p, 's'))) && (u.g(C.ci, u.c(k || z[14], k ? 0 : 6)) && k || (X = !1)),
g.vid = (S = u.s(s, {})).ci;
F(D)
};
var g = 'gaGlobal',
t = X,
s, P = {},
E = [],
K = [],
I = 0,
Z, Y = -1,
X = 0,
B = 0,
H = 0,
L = {},
k = N.userAgentData || {},
d = 'dataLayer',
b = 'brand',
m = 'mobile',
p = 'platform';
x = O.values(i.k),
y = O.keys(i.p),
z = O.values(i.p),
C = M(C, {
f: k[b + 's'] ? k[b + 's'].map((o) => o[b] + ';' + o.version).join('|') : V,
p: k[p] || /Mac|iP/.test(N[p]) ? 'macOS' : V,
m: (k[m] || /Mob|Pho/.test(N.userAgent) && N.maxTouchPoints > 1) * 1
});
g = W[g] = W[g] || {
from_cookie: !1,
hid: u.i()
};
W[d] && A(W[d]);
o.tag = (...o) => _(o[1], 's') in i.p ? Q(o[2] ? 'config' : 'set', ...o) : c.indexOf(o[0]) > -1 ? Q(...o) : T(...o)
})(o = {}),
o
})('document', Object, {}, 0, {}, 'tag.')), 'exports', 'object', 'tag'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment