Skip to content

Instantly share code, notes, and snippets.

@thyngster
Last active Apr 12, 2022
Embed
What would you like to do?
/* 2019-02-25
David Vallejo ( @ thyng )
New Google Analytics Linker Parameter Algo
version 0.1 Needs commenting
!!! Current version not properly generating the browser fingerprint . As usual the
linker value should be only valid for the next 2 minutes since it was generated.
Will review it
Note that GA library currently provides a public function to get the linker param
google_tag_data.glBridge.generate()
Use:
google_tag_data.glBridge.generate({
_ga: '121321321321.2315648466', // Google Analytics GA ID
_gac: undefined, // Google Remarketing ,not needed at all
_gid: '121321321321.2315648466' // Google ID
});
This glBridge ( Google Linker Bridge ? )tools provides same functionality as GA Linker / Decorate plugin, but
more likely to be used for All Google Suite products instead of just for Google Analytics
{
auto: ƒ,
decorate: ƒ,
generate: ƒ,
get: ƒ
}
*/
var generateLinkerParam = function(a) {
// Function to properly grab ID's from Cookies
var getCookiebyName = function(name) {
var pair = document.cookie.match(new RegExp(name + '=([^;]+)'));
return !!pair ? pair[1].match(/GA1\.[0-9]\.(.+)/)[1] : undefined;
};
// These are the 3 values used by the new linker
var cookies = {
_ga: getCookiebyName("_ga"),
// Google Analytics GA ID
_gac: undefined,
// Google Remarketing
_gid: getCookiebyName("_gid")// Google ID
};
// Calculate current browser_fingerprint based on UA, time, timezone and language
//
var browser_fingerprint = (function(a, b) {
var F = function(a) {
// Didnt check what this does, the algo just needs F to be defined. commenting out
Ne.set(a)
};
a = [window.navigator.userAgent, (new Date).getTimezoneOffset(), window.navigator.userLanguage || window.navigator.language, Math.floor((new Date).getTime() / 60 / 1E3) - (void 0 === b ? 0 : b), a].join("*");
if (!(b = F)) {
b = Array(256);
for (var c = 0; 256 > c; c++) {
for (var d = c, e = 0; 8 > e; e++)
d = d & 1 ? d >>> 1 ^ 3988292384 : d >>> 1;
b[c] = d
}
}
F = b;
b = 4294967295;
for (c = 0; c < a.length; c++)
b = b >>> 8 ^ F[(b ^ a.charCodeAt(c)) & 255];
return ((b ^ -1) >>> 0).toString(36);
}
)();
// Function to hash the cookie value
// The following functions takes a string and returns a hash value.
var hash_cookie_value = function(val) {
var A, C, D = function(a) {
A = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.";
C = {
"0": 52,
"1": 53,
"2": 54,
"3": 55,
"4": 56,
"5": 57,
"6": 58,
"7": 59,
"8": 60,
"9": 61,
"A": 0,
"B": 1,
"C": 2,
"D": 3,
"E": 4,
"F": 5,
"G": 6,
"H": 7,
"I": 8,
"J": 9,
"K": 10,
"L": 11,
"M": 12,
"N": 13,
"O": 14,
"P": 15,
"Q": 16,
"R": 17,
"S": 18,
"T": 19,
"U": 20,
"V": 21,
"W": 22,
"X": 23,
"Y": 24,
"Z": 25,
"a": 26,
"b": 27,
"c": 28,
"d": 29,
"e": 30,
"f": 31,
"g": 32,
"h": 33,
"i": 34,
"j": 35,
"k": 36,
"l": 37,
"m": 38,
"n": 39,
"o": 40,
"p": 41,
"q": 42,
"r": 43,
"s": 44,
"t": 45,
"u": 46,
"v": 47,
"w": 48,
"x": 49,
"y": 50,
"z": 51,
"-": 62,
"_": 63,
".": 64
};
for (var b = [], c = 0; c < a.length; c += 3) {
var d = c + 1 < a.length
, e = c + 2 < a.length
, g = a.charCodeAt(c)
, f = d ? a.charCodeAt(c + 1) : 0
, h = e ? a.charCodeAt(c + 2) : 0
, p = g >> 2;
g = (g & 3) << 4 | f >> 4;
f = (f & 15) << 2 | h >> 6;
h &= 63;
e || (h = 64,
d || (f = 64));
b.push(A[p], A[g], A[f], A[h])
}
return b.join("")
};
return D(String(val));
};
// Now we have all the data Let's build the linker String! =)
// First value is a fixed "1" value, the current GA code does the same. May change in a future
return ["1", browser_fingerprint, "_ga", hash_cookie_value(cookies._ga), "_gid", hash_cookie_value(cookies._gid)].join('*');
};
var decrypt_cookies_ids = function(a, b) {
var P = function(a) {
if (encodeURIComponent instanceof Function) return encodeURIComponent(a);
F(28);
return a
};
var m = function(a, b) {
for (var c in b) b.hasOwnProperty(c) && (a[c] = b[c])
};
var H = function() {
var a = {};
var b = window.google_tag_data;
window.google_tag_data = void 0 === b ? a : b;
a = window.google_tag_data;
b = a.gl;
b && b.decorators || (b = {
decorators: []
}, a.gl = b);
return b
};
var c = P(!!b);
b = H();
b.data || (b.data = {
query: {},
fragment: {}
}, c(b.data));
c = {};
if (b = b.data) m(c, b.query), a && m(c, b.fragment);
return c
}
// Example: decrypt_cookies_ids("1*qutsvh*_ga*MTczMjg1NDM3Ni4xNTUwMTAyNDc3*_gid*MTQwMzczNTA1OC4xNTUxMDIzOTA2");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment