I found this code for Google Analytics which lets you analyze just a subset of data for your analytics.
_gaq.push(['_setSampleRate', '80']);
I want to do the same thing with Mixpanel but from what I understand SetSampleRate is a function that is specific to Google Analytics.
How might I do something like this in Mixpanel?
I have browsed their KB & Help articles but haven't found anything that talks about this.
All you have to do is create a Random number from 0 to 100 and check if it's lower than the sample target you have. If it's lower you track it, otherwise you don't.
The way _setSampleRate works in Google Analytics is that it samples by user not by hit. So when you generate the Random number you also have to store it in a cookie so that you can check for further interactions and either track it or not.
In the Example below I created a helper function that checks if the user is in the Sample and handles the cookie logic for me.
function inSample(target) {
var domain_name = 'mysite.com'; // CUSTOMIZE WITH YOUR DOMAIN
var sampleCookie = 'mixpanel_sample='; // COOKIE NAME
var current = document.cookie;
if (current.indexOf(sampleCookie) > -1) {
// Cookie already exists use it
var current = document.cookie.substring(
document.cookie.indexOf(sampleCookie) + sampleCookie.length
);
if (current.indexOf(';') > -1)
current = current.substring(0,current.indexOf(';'));
current = parseInt(current);
} else {
// Cookie not found calculate a random number
current = Math.floor(Math.random()*100)
}
// reset the cookie to expire in 2 years
var two_years = new Date();
two_years.setTime(two_years.getTime() + 2*365*24*60*60*1000);
two_years = two_years.toGMTString();
document.cookie = sampleCookie + current +
'; domain=' + domain_name + '; path=/' +
' ; expires=' + two_years + ';'
return target >= current;
}
Now all you have to do is use this function in order to fire or not the mixPanel tracking Code.
if (inSample(80)) {
// MIXPANEL TRACKING CODE GOES HERE
}
What you have in the end is a report in Mixpanel that only includes 80% of your users.
Related
I'm curious if someone can help a very new Javascript user make sense of how to set a cookie, based on specific URL parameters. I see that pulling the data from the URL using JavaScript is covered in this post:
How can I get query string values in JavaScript?
But I can not figure out how to pull that information into a cookie to store the information throughout a users session on the site.
I would like to grab 3 main URL parameters:
utm_source
utm_medium
utm_campaign
And then store them in a cookie in Google Tag Manager using Javascript.
I can not wrap my head around making this happen. Any help would be greatly appreciated. Sorry I dont have much code to show for reference, but I have been experimenting ( and failing ) for hours now.
Thank you so much for any insight on this.
Cheer,
Melissa
Edit:
Sorry...I wasn't expecting someone to write it for me, I just didn't think my very failed attempts would help anyone see what I was trying to do so I just explained.
Here is my code as of now, and I know it's sort of working. I'm editing a previous cookie that stores the site referrer in a cookie. So as it stands right now, the cookie stores the referrer on the first pageview, then if you go to a different page it will show the {{utm_medium}} and continue to show that throughout the visit. I would like for it to not show the referrer, but output a cookie that displays {{utm_source}} | {{utm_medium}} | {{utm_campaign}} if that's even possible...
Thank you again for any help or pointers or articles. I really appreciate it.
<script> //get referrer info and shorten it
var ref = {{Referrer}}
function extractDomain(url) {
var domain;
//find & remove protocol (http, ftp, etc.) and get domain
if (url.indexOf("://") > -1) {
domain = url.split('/')[2];
} else {
domain = url.split('/')[0];
}
//find & remove port number
domain = domain.split(':')[0];
return domain;
}
ref = extractDomain(ref);
//create cookie
function createCookie(name, value, days) {
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
var expires = "; expires=" + date.toGMTString();
} else var expires = "";
document.cookie = name + "=" + value + expires + "; path=/";
}
var cookie = "";
//check if UTMs are present and set cookie content to the source utm
if ({{utm_source}}) {
createCookie("utmsource", cookie + {{utm_source}}, 1000)
} else if ({{utm_medium}}) {
createCookie("utmsource", cookie + "Email", 1000)
//check if referrer is present and set cookie content to the referrer
} else if ({{utm_campaign}}) {
createCookie("utmsource", cookie + "{{utm_campaign}}", 1000)
} else if {
createCookie("utmsource", cookie + "Email", 1000)
};
</script>
When you use cookie + something, you're not updating the cookie string. So each time you do this, you're just concatenating with the original, empty value of this string. Instead of calling setcookie multiple times, update the cookie string as you test the different variables, then call setcookie at the end with the combined value.
You shouldn't use else if between each test, since that will only add the second variable to the cookie if the first variable didn't exist. But you want all the variables put into the cookie.
var cookie = "";
if ({{utm_source}}) {
cookie += {{utm_source}};
}
if ({{utm_medium}}) {
cookie += ' | ' + {{utm_medium}};
} else {
cookie += ' | Email';
}
if ({{utm_campaign}}) {
cookie += ' | ' + {{utm_campaign}};
} else {
cookie += ' | Email';
}
setcookie('utm_source', cookie, 1000);
I need to track how many users have visited some page in the past 24 hours, and if the number of users goes over 50 in this time, then I want to display the dynamically summed cumulative user count for that timeframe.
I have previously used a basic combination of JS POST and PHP parsing on the back end like this:
$.post( "//api.link.here/using.php", { someParameter: 'xxx' }, function(data) {
if(data > 50) {
$('#much-visits').html('Hot Like Fire: '+data);
}
});
But am now working on a platform that doesn't allow me to edit PHP in any way, and this method has not been developed on this platform.
The Question:
Is it possible to accomplish this same/similar thing but with javascript only (frameworks/outside API calls allowed)?
It's impossible to do it solely using client-side JavaScript, because then you wouldn't have any unified record of how many visitors came to the site. You must have either a server-side element or a third-party element (such as Google Analytics).
Actually, you can! You need jQuery though, so if you can get that, you're good to go!
Every time a person visits the page, execute this function (change usercount to something more unique):
$.ajax({
url:"http://count.io/vb/usercount/users+",
type: "POST"
});
And when you want to read its value, call this function. Usercount is the unique string you made previously:
$.ajax({
url:"http://count.io/vb/usercount/",
success: function(data) {
alert(data.counts[0].count);
}
});
It's important to know that if someone gets to know the string, they might be able to hack the system so be wary of that.
I figured out how to do this with the help of user kabiroberai's answer regarding count.io.
Every time a person visits the page, execute this function (change usercount to something more unique):
$.ajax({
url:"http://count.io/vb/usercount/users+",
type: "POST"
});
And when you want to read its value, call this function. Usercount is the unique string you made previously:
$.ajax({
url:"http://count.io/vb/usercount/",
success: function(data) {
alert(data.counts[0].count);
}
});
NOTE: It's important to know that if someone gets to know the string, they might be able to hack the system so be wary of that.
The problem with this method is that it gives us the total count of all time, rather than the count of users from the past 24 hours.
To get the 24-hour count, we can do this:
// Timestamp shim for browsers
// Timestamp
var timestamp = Math.floor(Date.now());
// 24 hour old timestampt
var dayAgo = timestamp - 86400000;
// Record a hit to the count.io DB under DankStopProduct# group, as a timestmped hit of 1
var productNumber = $('.some-product-element').find('some-unique-identifier').attr('value'); //Doesn't have to be value, could be any unique identifier
$.ajax({
url:'http://count.io/vb/YourProduct' + productNumber + '/' + timestamp + '+',
type: 'POST'
});
// Make dynamic HTTP prefix that depends on the prefi of the site's current page protocol
var httpPrefix = (window.location.protocol === 'http:' ? 'http:' : 'https:');
// Retrieve current product array
$.post(
//I use CORS-anywhere to retrieve the data as otherwise there is a cross-origin problem
httpPrefix + '//cors-anywhere.herokuapp.com/' + 'http://count.io/vb/YourProduct' + productNumber,
function (data) {
var timedViewCounter = 0;
var myStringArray = data.counts;
var arrayLength = myStringArray.length;
// Check each "timestamped hit" in the current product's array to see if it's older than 24 hours
for (var i = 0; i < arrayLength; i++) {
var itemTimestamp = data.counts[i].item;
// Count up all the product hits that are 24 hours old or newer
if (itemTimestamp > dayAgo) {
timedViewCounter++;
}
}
// If total count is greater than 50, then output HTML onto page
var hotItem = '<div id="hot-item"><strong><i class="fa fa-fire"></i> Hot Like Fire!</strong> - ' +
'<span class="view-count">' + timedViewCounter + '</span> people have viewed this product in the last 24 hours</div>';
if (timedViewCounter > 50) {
$(".FreeShippingContainer").before(hotItem);
}
});
And that's all! Now the product view count will only be output if it's 51 views or higher in the past 24 hours.
I have been working on an extension for Google Chrome for some time now that allows users to share pages to Facebook using a simple browser action icon. It provides some additional functionality, such as allowing users to search through past links, etc. It has worked almost flawlessly up until I attempted to share one particular page (http://imgur.com/gallery/N0s079c) to my personal Facebook account today today. This is very concerning to me for a number of reasons, as it may mean that a similar problem may happen on additional pages and I want to patch the extension before my users run into it. Here's a (somewhat brief) rundown in how my extension shares links:
The user clicks the browser action and clicks "share" from a small menu in the popup. The popup page then sends a message using chrome.runtime.sendMessage() to the event page.
The event page processes the incoming message stream and acts appropriately, calling a function that uses chrome.tabs.query() to get the current tab. It then passes this information on to a function that queries a simple Web SQL database for an exact match of the URL to see if the user has shared it before. If they have, if gives them a basic confirm() dialog before continuing. If they haven't, the link is added to the database before continuing. I've included the code for this section below.
The extension processes the URL and generates a Facebook Feed dialog.
The Facebook Feed dialog redirects the user to a server page that either takes the user back to the link they shared or to the new Facebook post, depending on their settings.
When I attempt to share the link mentioned above, however, the extension doesn't do anything. There are no errors in the console for either the event or popup pages. I'm at a loss as to what may be causing it to fail. The only thing I can think of is that it is caused by some edge case bug in the Web SQL query. The way that it is currently set up, an error in the query would cause the code to simply stop executing. It was a basic SELECT column FROM table WHERE expression query that looks for exact matches, so I didn't feel the need to write any error handling in.
I tested several other links on Imgur to see if it was perhaps an issue specific to that site, but that didn't seem to be the case.
Code for Checking Shared Link History/Adding to History
simpleshare.shareLink.checkHistory = function(result) {
simpleshare.backend.database.transaction(function (tx) {
tx.executeSql('SELECT url FROM history WHERE url=\'' + result[0].url + '\'', [], function(tx, results) {
if(results.rows.length != 0) {
reshare = confirm('It appears that you\'ve already shared (or started to share) this link in the past.');
if (reshare == true) {
simpleshare.shareLink.share(result);
};
};
if(results.rows.length == 0) {
var today = new Date();
var month = today.getMonth();
var day = today.getDate();
var year = today.getFullYear();
if (month == 0) {
var monthAsWord = 'January';
};
if (month == 1) {
var monthAsWord = 'February';
};
if (month == 2) {
var monthAsWord = 'March';
};
if (month == 3) {
var monthAsWord = 'April';
};
if (month == 4) {
var monthAsWord = 'May';
};
if (month == 5) {
var monthAsWord = 'June';
};
if (month == 6) {
var monthAsWord = 'July';
};
if (month == 7) {
var monthAsWord = 'August';
};
if (month == 8) {
var monthAsWord = 'September';
};
if (month == 9) {
var monthAsWord = 'October';
};
if (month == 10) {
var monthAsWord = 'November';
};
if (month == 11) {
var monthAsWord = 'December';
};
var fullDate = monthAsWord + ' ' + day + ', ' + year;
tx.executeSql('INSERT INTO history VALUES (\'' + fullDate + '\', \'' + result[0].title + '\', \'' + result[0].url + '\')', [], function(tx, results) {
simpleshare.shareLink.share(result);
});
};
});
});
};
Heh, good question and this is a bit of a guess based on what you've said but I think I can tell you why it's that one page (and I know this because I've hit similar in the past before).
Your insert query:
INSERT INTO history VALUES (\'' + fullDate + '\', \'' + result[0].title + '\', \'' + result[0].url + '\')
Is going resolve to (for that page):
INSERT INTO history VALUES ('April 5, 2014', 'It's a graduated cylinder', 'http://imgur.com/gallery/N0s079c');
Which isn't valid, and you can see the problem in the syntax highlighting -- the It's, and specifically the single quote there, is ending that string early and making the rest of the query nonsense.
So, yes, this will happen on other pages, in fact an attacker to could guess what was happening and attempt to compromise the database with a cleverly crafted page title.
The lesson here is to sanitize anything you're using as an input to a SQL query. Actually never trust any input and validate/sanitize it on principal anyway.
Second lesson, and one I've failed to learn many times, if something can return an error -- catch it and do something with it.
Hope that helps.
I was interested in writing a twitter bot to help out some friends at a local ski resort. I found this tutorial from Amit Agarwal which gave me enough to get started (it did take me more than 5 minutes since I did a lot of modifying). I host the script on google docs.
FIRST I think this is javascript (my understanding is that google apps script uses javascript...) and when I have had problems with the code so far, google searches for javascript-such-and-such have been helpful, but if this is not actually javascript, please let me know so I can update the tag accordingly!
I have no prior experience with javascript, so I am pretty happy that it's actually working. But I want to see if I'm doing this right.
The start function initiates the trigger, which kicks off the fetchTweets() function every interval (30 minutes). In order to avoid duplicates (the first errors I encountered) & potentially being flagged as spam, I needed a way to ensure that I was not posting the same tweets over and over again. Within the start() function, the initial since_id value is assigned:
ScriptProperties.setProperty("SINCE_TWITTER_ID", "404251049889759234");
Within the fetchTweet() function, I think I am updating this property with the statement:
ScriptProperties.setProperty("SINCE_TWITTER_ID", lastID + '\n');
Is this a good way to do this? Or is there a better/more reliable way? And if so, how can I be sure it's updating the property? (I can check the log file and it seems to be doing it, so I probably just need to create a permanent text file for the logger).
Any help is greatly appreciated!!
/** A S I M P L E T W I T T E R B O T **/
/** ======================================= **/
/** Written by Amit Agarwal #labnol on 03/08/2013 **/
/** Modified by David Zemens #agnarchy on 11/21/2013 **/
/** Tutorial link: http://www.labnol.org/?p=27902 **/
/** Live demo at http://twitter.com/DearAssistant **/
/** Last updated on 09/07/2013 - Twitter API Fix **/
function start() {
Logger.log("start!" + '\n')
// REPLACE THESE DUMMY VALUES
// https://script.google.com/macros/d/18DGYaa-jbaAK9rEv0HZ2cMcWjFGgkvVcvr6TfksMNbbu2Brk3gZeZ46R/edit
var TWITTER_CONSUMER_KEY = "___REDACTED___";
var TWITTER_CONSUMER_SECRET = "___REDACTED___";
var TWITTER_HANDLE = "___REDACTED___";
var SEARCH_QUERY = "___REDACTED___" + TWITTER_HANDLE;
// Store variables
ScriptProperties.setProperty("TWITTER_CONSUMER_KEY", TWITTER_CONSUMER_KEY);
ScriptProperties.setProperty("TWITTER_CONSUMER_SECRET", TWITTER_CONSUMER_SECRET);
ScriptProperties.setProperty("TWITTER_HANDLE", TWITTER_HANDLE);
ScriptProperties.setProperty("SEARCH_QUERY", SEARCH_QUERY);
ScriptProperties.setProperty("SINCE_TWITTER_ID", "404251049889759234");
// Delete exiting triggers, if any
var triggers = ScriptApp.getScriptTriggers();
for(var i=0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i]);
}
// Setup trigger to read Tweets every 2 hours
ScriptApp.newTrigger("fetchTweets")
.timeBased()
.everyMinutes(30)
//.everyHours(2)
.create();
}
function oAuth() {
//Authentication
var oauthConfig = UrlFetchApp.addOAuthService("twitter");
oauthConfig.setAccessTokenUrl("https://api.twitter.com/oauth/access_token");
oauthConfig.setRequestTokenUrl("https://api.twitter.com/oauth/request_token");
oauthConfig.setAuthorizationUrl("https://api.twitter.com/oauth/authorize");
oauthConfig.setConsumerKey(ScriptProperties.getProperty("TWITTER_CONSUMER_KEY"));
oauthConfig.setConsumerSecret(ScriptProperties.getProperty("TWITTER_CONSUMER_SECRET"));
}
function fetchTweets() {
oAuth();
// I put this line in to monitor whether the property is getting "stored" so as to avoid
// reading in duplicate tweets.
Logger.log("Getting tweets since " + ScriptProperties.getProperty("SINCE_TWITTER_ID"))
var twitter_handle = ScriptProperties.getProperty("TWITTER_HANDLE");
var search_query = ScriptProperties.getProperty("SEARCH_QUERY")
Logger.log("searching tweets to " + search_query + '\n');
// form the base URL
// restrict to a certain radius ---:
//var search = "https://api.twitter.com/1.1/search/tweets.json?count=5&geocode=42.827934,-83.564306,75mi&include_entities=false&result_type=recent&q=";
// unrestricted radius:
var search = "https://api.twitter.com/1.1/search/tweets.json?count=5&include_entities=false&result_type=recent&q=";
search = search + encodeString(search_query) + "&since_id=" + ScriptProperties.getProperty("SINCE_TWITTER_ID");
var options =
{
"method": "get",
"oAuthServiceName":"twitter",
"oAuthUseToken":"always"
};
try {
var result = UrlFetchApp.fetch(search, options);
var lastID = ScriptProperties.getProperty("SINCE_TWITTER_ID");
if (result.getResponseCode() === 200) {
var data = Utilities.jsonParse(result.getContentText());
if (data) {
var tweets = data.statuses;
//Logger.log(data.statuses);
for (var i=tweets.length-1; i>=0; i--) {
// Make sure this is a NEW tweet
if (tweets[i].id > ScriptProperties.getProperty("SINCE_TWITTER_ID")) {
lastID = (tweets[i].id_str);
var answer = tweets[i].text.replace(new RegExp("\#" + twitter_handle, "ig"), "").replace(twitter_handle, "");
// I find this TRY block may be necessary since a failure to send one of the tweets
// may abort the rest of the loop.
try {
Logger.log("found >> " + tweets[i].text)
Logger.log("converted >> " + answer + '\n');
sendTweet(tweets[i].user.screen_name, tweets[i].id_str, answer.substring(0,140));
// Update the script property to avoid duplicates.
ScriptProperties.setProperty("SINCE_TWITTER_ID", lastID);
Logger.log("sent to #" + tweets[i].user.screen_name + '\n');
} catch (e) {
Logger.log(e.toString() + '\n');
}
}
}
}
}
} catch (e) {
Logger.log(e.toString() + '\n');
}
Logger.log("Last used tweet.id: " + lastID + + "\n")
}
function sendTweet(user, reply_id, tweet) {
var options =
{
"method": "POST",
"oAuthServiceName":"twitter",
"oAuthUseToken":"always"
};
var status = "https://api.twitter.com/1.1/statuses/update.json";
status = status + "?status=" + encodeString("RT #" + user + " " + tweet + " - Thanks\!");
status = status + "&in_reply_to_status_id=" + reply_id;
try {
var result = UrlFetchApp.fetch(status, options);
Logger.log("JSON result = " + result.getContentText() + '\n');
}
catch (e) {
Logger.log(e.toString() + '\n');
}
}
// Thank you +Martin Hawksey - you are awesome
function encodeString (q) {
// Update: 09/06/2013
// Google Apps Script is having issues storing oAuth tokens with the Twitter API 1.1 due to some encoding issues.
// Henc this workaround to remove all the problematic characters from the status message.
var str = q.replace(/\(/g,'{').replace(/\)/g,'}').replace(/\[/g,'{').replace(/\]/g,'}').replace(/\!/g, '|').replace(/\*/g, 'x').replace(/\'/g, '');
return encodeURIComponent(str);
// var str = encodeURIComponent(q);
// str = str.replace(/!/g,'%21');
// str = str.replace(/\*/g,'%2A');
// str = str.replace(/\(/g,'%28');
// str = str.replace(/\)/g,'%29');
// str = str.replace(/'/g,'%27');
// return str;
}
When you use ScriptProperties.setProperty("KEY", "VALUE");, internally Script Properties will overwrite a duplicate key (i.e., if an old Property has the same key, your new one will replace it). So in your case, since you are using the same identifier for the key (SINCE_TWITTER_ID), it will replace any previous Script Property that is that key.
Furthermore, you can view Script Properties via File -> Project properties -> Project properties (tab). Imo Google didn't name that very well. User properties as specific to Google users. Script properties as specific to the Script Project you are working under.
Also, it probably isn't a good idea to include \n in your value when you set the property. That will lead to all sorts of bugs down the road, because you'll have to compare with something like the following:
var valToCompare = "My value\n";
instead of:
var valToCompare = "My value";
because the value in SINCE_TWITTER_ID will actually be "some value\n" after you call your fetchTweet() function.
Of course, one seems more logical I think, unless you really need the line breaks (in which case you should be using them somewhere else, for this application).
Its ok like that thou I dont know why you are adding \n at fhe end. Might confuse other code. You can see script properties in the script's file menu+ properties
I see a decent amount of traffic, around 100 visits a day, that comes from an images.google domain but shows as referral traffic rather than organic in Google Analytics. I have some custom code to pull keywords out and set an organic source for a few variations of what Google Image Search referrers look like, and it works for every referrer I can run it against from the server log.
var ref = document.referrer;
if (ref.search(/www.google/) != -1 && ref.search(/imgres/) != -1) {
var regex = new RegExp("www.google.([^\/]+).*");
var match = regex.exec(ref);
ref = 'http://images.google.' + match[1] + '?' + ref.split('?')[1];
_gaq.push(['_setReferrerOverride', ref]);
} else if (ref.search(/maps.google/) != -1 && ref.search(/q=/) == -1) {
var regex = new RegExp("maps.google.([^\/]+).*");
var match = regex.exec(ref);
ref = 'http://maps.google.' + match[1] + '?q=' + encodeURIComponent('(not provided)');
_gaq.push(['_setReferrerOverride', ref]);
}
function splitUrl(url) {
var vals = {};
var split = url.split('?');
vals.base = split[0];
if(split.length > 1) {
var vars = split[1].split('&');
vals.params = {};
for(var i = 0, len = vars.length; i < len; i++) {
var valSplit = vars[i].split('=', 2);
vals.params[valSplit[0]] = valSplit[1];
}
}
return vals;
}
function joinUrl(urlObj) {
var vars = [];
for(key in urlObj.params)
if(urlObj.params.hasOwnProperty(key))
vars.push(key + '=' + urlObj.params[key]);
return urlObj.base + '?' + vars.join('&');
}
//fix keyword for old google image search
if(ref.match(/^http:\/\/images\.google\./) || ref.match(/^http:\/\/images\.google$/)) {
var refUrl = splitUrl(ref);
if(refUrl.params.prev && !refUrl.params.q) {
var prev = decodeURIComponent(refUrl.params.prev);
if(prev.indexOf('?q=') !== -1 || prev.indexOf('&q=') !== -1) {
var prevUrl = splitUrl(prev);
refUrl.params.q = prevUrl.params.q;
if(!refUrl.params.q)
refUrl.params.q = encodeURIComponent('(not provided)');
delete prevUrl.params.q;
refUrl.params.prev = encodeURIComponent(joinUrl(prevUrl));
}
_gaq.push(['_setReferrerOverride', joinUrl(refUrl)]);
} else if(!refUrl.params.q) {
refUrl.params.q = encodeURIComponent('(not provided)');
_gaq.push(['_setReferrerOverride', joinUrl(refUrl)]);
}
}
_gaq.push(['_addOrganic', 'images.google', 'q']);
_gaq.push(['_addOrganic', 'maps.google', 'q', true]);
This handles all of the referres that look like:
http://images.google.com/?q=
and
http://www.google.com/?imgres=
I don't know where the referral traffic is coming from. Has anyone else seen this?
Well it is natural for Google to recognize this domain as a referral as GA only includes by default a certain number of domains as Search Engines.
To solve this problem you can include such domain as a Search Engine using the "addOrganic()" Method.
To use this method, you must specify not only the domain of the search engine, but also the query string parameter used for searches. In the case of images.google.com it's "q".
On your GA tracking code, add the line:
_gaq.push(['_addOrganic', 'images.google.com', 'q', true]);
You can get more info on the Ga Help Site.
Hope this info helps,
Augusto Roselli
Web Analytics - digitalcube
#_digitalcube
www.dp6.com.br
If someone clicks on an image that shows up on standard google search, not images.google, the url might be different. You should try some urls from there. But besides that, the google images links that popup on normal Google will not include the query string if the user is logged in into a Google Account. It happened on Oct 2011 here are a couple of links on the subject:
Official Google Statement
Avinash's, always worth reading, opinion.
On normal organic google links Google Analytics shows these visits as coming from a (not provided) keyword from an organic medium. But if you click on an image on the SERP it won't be identified as an organic medium. It will be identified as a Referral, and that's probably the ones you are seeing.
So what you need to do is to verify if the google images link has the q parameter or not. If it doesn't have than it's coming from a logged user and should be reported as (not provided) to be consistent with google organic keywords. Just append &q=(not provided) to the _setReferrerOverride url you got. Remember to url encode that before appending to the url.
I'm also posting here the code I use. It's from Google Forums. But it's very similar to yours and doesn't handle the (not provided) keywords issue yet.
Note that it's very similar to yours with a few notable differences.
You strip the whole path from the images url, while mine keeps the
path.
You don't use the "true" keyword on "_addOrganic", that
may cause Google Images to be reported as google instead of
images.google source on your reports.
Here's the code I currently use:
//handle google images referrer
var ref = document.referrer;
if ((ref.search(/google.*imgres/) != -1)) {
var regex = new RegExp("\.google\.([^\/]+)(.*)");
var match = regex.exec(ref);
_gaq.push(
['_setReferrerOverride', 'http://images.google.' + match[1] +
unescape(match[2])],
['_addOrganic', 'images.google', 'q', true]
);
}
I'll be updating my code to handle (not provided) google images links and will post here as soon as I have it.