Using the latest analytics.js code (as of today) is there a way through their JS API I can get the session id?
If you're talking about the client ID, you can get that as follows:
ga(function(tracker) {
var clientId = tracker.get('clientId');
console.log(clientId);
});
Here's where that's stated in the documentation:
https://developers.google.com/analytics/devguides/collection/analyticsjs/cookies-user-id#getting_the_client_id_from_the_cookie
Keep in mind that the client ID is (usually) stored in a cookie, so if the user clears their cookies, they'll be assigned a new client ID that may not match the one you have.
You can read the cookie created by Google but:
It's a privately (by google) chosen variable name/format and could change at any time, thus breaking your code
It appears to break their TOS if you store that information
https://webmasters.stackexchange.com/questions/51866/can-you-track-one-users-session-with-google-analytics-by-using-the-utma-cooki
Linking Google Analytics event logs to unique session ID
http://www.analytics-ninja.com/blog/2011/08/how-google-analytics-calculates-visits.html
Be aware! Some ad-blockers like uBlock Origin replaces GA script with its own polyfill.
This means that you can't correctly check is it real GA script are loaded on your page.
Also uBlock's polyfill changes GA API, so when you using ga(function(tracker){}) callback will never called!
So don't relay on callback and never wait for its calling
The better way is to manually store custom clientId in cookie and tell this clientId to GA
https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference?hl=en#clientId
Related
On Google Analytics, in Javascript, is there a way to tie certain behavior to which session ID a user is on?
For example, every time the user changes GA sessions, we want to show the user a different version of the site.
It seems that GA doesn't really offer up the session ID.
We are tracking site versions via Google Analytics custom events. So if there's a way to see which custom events have previously been called for this session, that would also solve the problem.
Something like this would be ideal:
ga(function(tracker) {
var clientId = tracker.get('clientId');
});
However, that is only for the clientId, not for the session ID.
GA UA (analytics.js) doesn't surface session ids. GA UA calculates/generates them later on because of how complex the rules for them are.
GA4 (gtag.js) does generate a session id and stores it on the front-end since the rules for sessions are now way simpler. It stores it in a cookie that starts from _ga and then has your tracking code in it. Here is how it looks here, on this page on SO:
Finally, here is how you get the value from gtag (it's cleaner than parsing the cookie):
gtag('get', 'G-WCZ03SZFCQ', 'session_id', (field) => console.log(field))
If you want to read more on gtag api, here's the documentation.
Note that it wants a callback to get the field:
Not sure why Google decided to make the get function async just to get a cookie. Probably they just decided to follow the same pattern and some items to require async for some reason.
Google Analytics does not provide a way to access the session ID directly. However, you can use the clientId to tie certain behavior to a user's session.
The clientId is a unique identifier that is generated by GA for each user. It is stored in the browser's cookies, and is used to identify a user across multiple sessions.
You can use the ga function to access the clientId as you mentioned in your example:
ga(function(tracker) {
var clientId = tracker.get('clientId');
// use the clientId to tie certain behavior to a user's session
});
You can also use custom events to track different versions of the site, as you mentioned. You can then use the clientId to see which custom events have previously been called for a user's session.
It's worth noting that if you're using GA cookies with the same domain across different subdomains, you'll have to use the linker plugin to properly track the client ID across those subdomains.
ga('create', 'GA_MEASUREMENT_ID', 'auto', {'allowLinker': true});
ga('require', 'linker');
ga('linker:autoLink', ['domain1.com', 'domain2.com']);
In summary, while GA does not offer a direct way to access the session ID, you can use the clientId and custom events to tie certain behavior to a user's session and track different version of the site.
I have an app where we track user id's from session and pass to custom metric in Google Analytics.
What we're seeing is that if you log out, and log back in as a different user, both users will use the latest user id within google analytics.
Is it possible to "clear" this common link between each session so that each sign in starts it's own session in GA?
Here's the same thread topic on ga forum: https://support.google.com/analytics/thread/96259041?hl=en
You have to set the clientId when you create the tracker. i.e.:
ga('create', 'UA-XXXX-Y', {
'clientId': '<my custom clientid>'
});
You will have to find a way to get it new on next time and pass it to the snippet above (or via GTM). For example, you can write it in a cookie that is deleted when you close the browser, in this way for the entire duration of the navigation it will be maintained and the next time you open the browser you have another one created and you will use that, and so on.
I'm making a chrome extension that injects an iframe on a webpage and show some stuff.
Content loaded in iframe is from https://example.com and i have full control over it. I'm trying to access cookies of https://example.com from the iframe (which i think should be available) by document.cookie. This is not letting me access httponly flagged cookie and i do not know reason for this. After all this is no cross-domain. Is it?
Here is the code i'm using to get cookie
jQuery("#performAction").click(function(e) {
e.preventDefault();
console.log(document.domain); // https://example.com
var cookies = document.cookie;
console.log('cookies', cookies);
var httpFlaggedCookie1 = getCookie("login_sess");
var httpFlaggedCookie2 = getCookie("login_pass");
console.log('httpFlaggedCookie1 ', httpFlaggedCookie1 ); // shows blank
console.log('httpFlaggedCookie2 ', httpFlaggedCookie2 ); // shows blank
if(httpFlaggedCookie2 != "" && httpFlaggedCookie2 != ""){
doSomething();
} else{
somethingElse();
}
});
Any suggestions what can be done for this?
By default in Chrome, HttpOnly cookies are prevented to be read and written in JavaScript.
However, since you're writing a chrome extensions, you could use chrome.cookies.get and chrome.cookies.set to read/write, with cookies permissions declared in manifest.json. And be aware chrome.cookies can be only accessed in background page, so maybe you would need to do something with Message Passing
Alright folks. I struggled mightily to make httponly cookies show up in iframes after third party cookies have been deprecated. Eventually I was able to solve the issue:
Here is what I came up with:
Install a service worker whose script is rendered by your application server (eg in PHP). In there, you can output the cookies, in a closure, so no other scripts or even injected functions can read them. Attempts to load this same URL from other user-agents will NOT get the cookies, so it’s secure.
Yes the service workers are unloaded periodically, but every time it’s loaded again, it’ll have the latest cookies due to #1.
In your server-side code response rendering, for every time you add a Set-Cookie header, also add a Set-Cookie-JS header with the same content. Make the Service Worker intercept this response, read that cookie, and update the private object in the closure.
In the “fetch” event, add a special request header such as Cookie-JS, and pass what would have been passed in the cookie. Add this to the request headers before sending the request to the server. In this way, you can send all “httponly” cookies back to the server, without the Javascript being able to see them, even if actual cookies are blocked!
On your server, process the Cookie-JS header and merge that into your usual Cookies mechanism, then proceed to run the rest of your code as usual.
Although this seems secure to me — I’d appreciate if anyone reported a security flaw!! — there is a better mechanism than cookies.
Consider using non-extractable private keys such as ECDSA to sign hashes of payloads, also using a service worker. (In super-large payloads like videos, you may want your hash to sample only a part of the payload.) Let the client generate the key pair when a new session is established, and send the public key along with every request. On the server, store the public key in a session. You should also have a database table with the (publicKey, cookieName) as the primary key. You can then look up all the cookies for the user based on their public key — which is secure because the key is non-extractable.
This scheme is actually more secure than cookies, because cookies are bearer tokens and are sometimes subject to session fixation attacks, or man-in-the-middle attacks (even with https). Request payloads can be forged on the server and the end-user cannot prove they didn’t make that request. But with this second approach, the user’s service worker is signing everything on the client side.
A final note of caution: the way the Web works, you still have to trust the server that hosts the domain of the site you’re on. It could just as easily ship JS code to you one day to sign anything with the private key you generated. But it cannot steal the private key itself, so it can only sign things when you’ve loaded the page. So, technically, if your browser is set to cache a top-level page for “100 years”, and that page contains subresource integrity on each resource it loads, then you can be sure the code won’t change on you. I wish browsers would show some sort of green padlock under these conditions. Even better would be if auditors of websites could specify a hash of such a top-level page, and the browser’s green padlock would link to security reviews published under that hash (on, say, IPFS, or at a Web URL that also has a hash). In short — this way websites could finally ship code you could trust would be immutable for each URL (eg version of an app) and others could publish security audits and other evaluations of such code.
Maybe I should make a browser extension to do just that!
I have JS code that runs on my clients' websites and occasionally reports certain events to GA so that the clients can track them (they are almost click events). For clients that use universal analytics the code I use is:
if (typeof ga != "undefined") ga('send', 'event', category, action,opt_label);
and usually it works correctly (I'm using the GA debugger extension for chrome to see which values are sent) however with a couple of clients the GA debugger extension returns an error:
Command ignored. Unknown target: undefined
What does the error mean and why does it happen only on some sites?
In the error message:
Unknown target: undefined
The word "target" refers to the tracker object. If you're using GTM, it creates its own named tracker object in order to not conflict with any existing trackers on the page. But if there's no default tracker already on the page, then any ga('send', ...) or ga('set', ...) command will fail because they target the default tracker (which in this case doesn't exist).
This is normally not a problem because most analytics.js users use the default tracker, and most GTM user do 100% of their implementation configuration in GTM, and don't write analytics.js code at all, but if you do need to write your own analytics.js code and use GTM, you'll need to get the GTM tracker object, since the default tracker syntax won't work.
You can get a list of all created trackers in the following way, then you can send the event using the synchronous calling syntax:
ga(function() {
var allTrackers = ga.getAll();
var firstTracker = allTrackers[0];
firstTracker.send('event', category, action, opt_label);
});
Obviously if you have more than one tracker, you'll have to figure out which one is the GTM tracker.
For more information on working with named tracker objects and/or using multiple trackers, check out this developer guide:
https://developers.google.com/analytics/devguides/collection/analyticsjs/creating-trackers#working_with_multiple_trackers
The Google Analytics User ID documentation page shows that you set the User ID when you create the tracker. I have a javascript only project with sign-in after page load, is there any way to set the User ID after login? Something like ga("set", "userid", "UNIQUEID")
On the field reference page it says you can only set user-id in the create function. Are we able to call create again with the user-id? Will that create a new tracker, or override the old one?
EDIT: The beta version of User ID tracking showed that you could specify the userid after creating the tracker using ga('set', '&uid', {{ USER_ID }}); and that would try to unify the session from before the userid was set with the one after. That seems to be very different than what the docs current specify. Is there any way to do this with the current method?
This one works
ga('set', '&uid', '<dynamic user id here>');
The documentation seems to indicate that, with analytics.js, you should do the following:
// Alternatively, you may set the user ID via the `set` method.
ga('set', 'userId', 'as8eknlll');
I'm not sure how this differs from the current answer (which uses &uid), but this solution is working for us.
You should set userId beofre sending event to Google Analytics. I couldn't manage to send userId after sending events pageview and ecommerce:send.
It appears from Justin Cutroni's blog that he's saying that data stitching (in your case matching the userid prior to login to the userid post-login) is not currently offered in Google Analytics.
http://cutroni.com/blog/2014/04/10/understanding-cross-device-measurement-and-the-user-id/
See specifically this sentence: "Google Analytics will not go back in time and stitch every single session from a given user together."
If you are using Google Tag Manager you can set the User ID by added '&uid' as a field to your Google Analytics Setting variable: