Still a work in progress, not ready for usage.
Tries to mim Classic Google Analytics methodology to calculate traffic source client side.
On Universal Analytics all this is calculated server side, so it's unavailable in case you need it client side.
| (function(){ | |
| try{ | |
| var prefix = "traffic_"; | |
| var sourceCookieName = prefix + "source"; | |
| var mediumCookieName = prefix + "medium"; | |
| var gclidCookieName = prefix + "gclid"; | |
| var channelCookieName = prefix + "channel"; | |
| var cidCookieName = prefix + "cid"; | |
| var deviceCategoryCookieName = prefix + "device_category"; | |
| function getParam(s, q) { | |
| try{ | |
| if(s.indexOf('?') == 0){ | |
| return s.substr(1).match(RegExp('(^|&)'+q+'=([^&]*)'))[2]; | |
| }else{ | |
| return s.match(RegExp('(^|&)'+q+'=([^&]*)'))[2]; | |
| } | |
| } catch(e){ | |
| return ''; | |
| }; | |
| }; | |
| function getCookie(cname) { | |
| var name = cname + "="; | |
| var ca = document.cookie.split(';'); | |
| for(var i = 0; i < ca.length; i++) { | |
| var c = ca[i]; | |
| while (c.charAt(0) == ' ') { | |
| c = c.substring(1); | |
| } | |
| if (c.indexOf(name) == 0) { | |
| return c.substring(name.length, c.length); | |
| } | |
| } | |
| return ""; | |
| } | |
| function calculateTrafficSource(hostname) { | |
| var source='', medium='', campaign='', term='', content='', gclid=''; | |
| var search_engines = [['bing', 'q'], ['google', 'q'], ['yahoo', 'q'], ['ask', 'q'], ['msn', 'q']]; | |
| var ref = document.referrer; | |
| ref = ref.substr(ref.indexOf('//')+2); | |
| ref_domain = ref; | |
| ref_path = '/'; | |
| ref_search = ''; | |
| // Checks for campaign parameters | |
| var url_search = document.location.search; | |
| gclid = getParam(url_search, 'gclid'); | |
| if (gclid && ref_domain.indexOf("google") > -1) { | |
| source = getParam(url_search, 'utm_source') ||'google'; | |
| medium = 'cpc'; | |
| campaign = getParam(url_search, 'utm_campaign'); | |
| } else if(gclid){ | |
| source = getParam(url_search, 'utm_source') || ref.substr(0,ref.indexOf('/')); | |
| medium = 'display'; | |
| campaign = getParam(url_search, 'utm_campaign'); | |
| } else if(url_search.indexOf('utm_source') > -1) { | |
| source = getParam(url_search, 'utm_source'); | |
| medium = getParam(url_search, 'utm_medium'); | |
| campaign = getParam(url_search, 'utm_campaign'); | |
| term = getParam(url_search, 'utm_term'); | |
| content = getParam(url_search, 'utm_content'); | |
| } else if(ref) { | |
| // separate domain, path and query parameters | |
| if (ref.indexOf('/') > -1) { | |
| ref_domain = ref.substr(0,ref.indexOf('/')); | |
| ref_path = ref.substr(ref.indexOf('/')); | |
| if (ref_path.indexOf('?') > -1) { | |
| ref_search = ref_path.substr(ref_path.indexOf('?')+1); | |
| ref_path = ref_path.substr(0, ref_path.indexOf('?')); | |
| } | |
| } | |
| medium = 'referral'; | |
| source = ref_domain; | |
| // Extract term for organic source | |
| for (var i=0; i<search_engines.length; i++){ | |
| if(ref_domain.indexOf(search_engines[i][0]) > -1){ | |
| medium = 'organic'; | |
| source = search_engines[i][0]; | |
| term = getParam(ref_search, search_engines[i][1]) || '(not provided)'; | |
| break; | |
| } | |
| } | |
| if(source && source.indexOf(hostname) > -1){ | |
| source = 'direct'; | |
| medium = '(none)'; | |
| }; | |
| }else{ | |
| source = 'direct'; | |
| medium = '(none)'; | |
| }; | |
| if(!gclid){ | |
| gclid = ""; | |
| } | |
| var value = { | |
| 'source' : source, | |
| 'medium' : medium, | |
| 'gclid' : gclid, | |
| 'device_category' : getDeviceCategory(), | |
| 'cid' : getClientId({{cons live tracking id}}) | |
| }; | |
| value.channel = getChannel(value); | |
| return value; | |
| }; | |
| function getTrafficSource(hostname) { | |
| var trafficSources = calculateTrafficSource(hostname); | |
| var cookieTraffic = { | |
| 'source' : getCookie(sourceCookieName), | |
| 'medium' : getCookie(mediumCookieName), | |
| 'gclid' : getCookie(gclidCookieName), | |
| 'device_category' : getCookie(deviceCategoryCookieName), | |
| 'cid' : getCookie(cidCookieName), | |
| 'channel' : getCookie(channelCookieName) | |
| } | |
| var value = trafficSources; | |
| if(trafficSources.source == 'direct' && cookieTraffic.source) { | |
| // Use new value if not self-referral | |
| value = cookieTraffic; | |
| } | |
| return value; | |
| }; | |
| function getClientId(trackingId) { | |
| try { | |
| var trackers = ga.getAll(); | |
| var i, len; | |
| for (i = 0, len = trackers.length; i < len; i += 1) { | |
| if (trackers[i].get('trackingId') === trackingId) { | |
| return trackers[i].get('clientId'); | |
| } | |
| } | |
| } catch(e) {} | |
| return 'false'; | |
| } | |
| function getDeviceCategory() { | |
| var userAgent = navigator.userAgent || navigator.vendor || window.opera; | |
| var device = 'desktop' | |
| if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4))){ | |
| if(/android|ipad|playbook|silk/i.test(userAgent)){ | |
| device = 'tablet'; | |
| }else{ | |
| device = 'mobile'; | |
| }; | |
| }; | |
| return device | |
| }; | |
| function getChannel(traffic){ | |
| var channel = ""; | |
| var socialRegex = /^(social|social-network|social-media|sm|social network|social media)$/; | |
| var socialMediaRegex = /google+|facebook|twitter|qzone|sina weibo|instagram|habbo|vk|tumblr|linkedin|renren|bebo|tagged|orkut|netlog|friendster|hi5|flixster|mylife|classmates.com|sonico.com|plaxo|douban|odnoklassniki|viadeo|flickr|weeworld|last.fm|myspace|myheritage|xanga|deviantart|mixi|cyworld|gaia online|skyrock|foursquare|fotolog|we heart it|stumbleupon|blackplanet|friends reunited|academia.edu|livejournal|studivz|geni.com|goodreads|tuenti|busuu|xing|taringa!|nasza-klasa.pl|wayn|soundcloud|buzznet|care2|caringbridge|stickam|delicious|my opera|about.me|open diary|livemocha|trombi.com|weread|ibibo|untappd|tylted|ravelry|43 things|mocospace|jiepang|couchsurfing|fetlife|draugiem.lv|rooster teeth|etoro|itsmy|kiwibox|grindr|grono.net|dxy.cn|getglue|vampirefreaks.com|fotki|english, baby!|travbuddy.com|nexopia|librarything|cafemom|uplike|streetlife|minds|zoo.gr|focus.com|influenster|diaspora*|asmallworld|irc-galleria|ryze|reverbnation.com|italki.com|gather.com|millatfacebook|girlsaskguys|socialvibe|biip.no|skoob|doximity|identi.ca|indaba music|hospitality club|partyflock|travellerspoint|gamerdna|smartican|filmaffinity|spot.im|laibhaari|mubi|hr.com|elftown|stage 32|cozycot|athlinks|goodwizz|patientslikeme|gays.com|elixio|hotlist|writeaprisoner.com|fuelmyblog|dol2day|hub culture|late night shots|advogato|poolwo|the sphere|anobii|asianavenue|audimated.com|bolt.com|cloob|clusterflunk|crunchyroll|cucumbertown|dailybooth|dailystrength|disaboom|dontstayin|dreamwidth|ello|eons.com|epernicus|experience project|exploroo|filmow|fledgewing|friendica|fyuse|gapyear.com|gentlemint|gogoyoko|govloop|jaiku|kaixin001|lifeknot|linkexpats|listography|makeoutclub|meetin|meettheboss|meetup (website)|mog|mouthshut.com|ning|outeverywhere|pingsta|pinterest|playfire|playlist.com|plurk|qapacity|quechup|quora|raptr|sciencestage|sgrouples|sharethemusic|shelfari|spaces|spring.me|students circle network|talkbiznow|taltopia|teachstreet|termwiki|tribe.net|tsu|virb|vox|wattpad|wellwer|wepolls.com|wer-kennt-wen|wooxie|xt3|yammer|yelp, inc.|yookos/; | |
| var paidSearchRegex = /^(cpc|ppc|paidsearch)$/; | |
| var otherAdvertisingRegex = /^(cpv|cpa|cpp|content-text)$/; | |
| var displayRegex = /^(display|cpm|banner)$/; | |
| if((traffic.source == "direct" && traffic.medium == "(not set)") || traffic.medium == "(none)"){ | |
| channel = "Direct"; | |
| } | |
| else if(traffic.medium == "organic"){ | |
| channel = "Organic Search"; | |
| } | |
| else if(socialRegex.test(traffic.medium) && "51.com:academia:activerain:addthis:allnurses:allrecipes:allvoices:ameba:android central:anobii:answerbag:aol answers:ask ubuntu:askville:baby gaga:babyblog:before it's news:bigtent:bitly:blogcu:bloggang:blogger:blogher:bloglines:blogs.com:blogsome:blogster:blurtit:buzzfeed:buzznet:cafemom:care2:caringbridge:catster:cg hub:chicagonow:circle of moms:cocolog:couchsurfing:crunchyroll:cyworld:dailybooth:dailymotion:dailystrength:delicious:deviantart:digg:diigo:disqus:dogster:douban:draugiem.lv:drugs-forum:dzone:experience project:facebook:facebook apps:families.com:fanpop:fark:fc2:feministing:ffffound!:filmaffinity:flavors.me:flickr:foodservice.com:formspring:foursquare:friendfeed:fubar:gaia online:gather:glassdoor:goldenline:goo blog:goo.gl:goodreads:google groups:google+:govloop:gutefrage.net:hacker news:hatena bookmark:hatena diary:hootsuite:identi.ca:imvu:insanejournal:instapaper:internations:interpals:jappy:jigsaw:justin.tv:kaboodle:klicknation:last.fm:librarything:linkedin:listal:livejournal:meetup:meneame:metroflog:mixi:mubi:my modern met:my opera:myfamily:myspace:naver:netlog:netvibes:nico nico douga:ning:nk.pl:nowpublic:odnoklassniki:okwave:one world:onstartups:open diary:orkut:oshiete! goo:paper.li:photobucket:pinboard:pinterest:pixiv:plaxo:plurk:pocket:polyvore:posterous:quora:ravelry:reddit:renren:researchgate:reverbnation:sciencestage:scribd:sina weibo:skyrock:slashdot:slideshare:sonico:spoke:squidoo:stack exchange:stack overflow:stumbleupon:super user:tagged:taringa!:techmeme:tinyurl:topix:travbuddy:tripadvisor:tudou:tuenti:tumblr:tweetdeck:twitter:typepad:ustream:vampirefreaks.com:viadeo:vimeo:virb:vkontakte:wattpad:weebly:wer-kennt-wen:wer-weiss-was:wikia:wikianswers:wikihow:wikitravel:wiserearth:woot:wordpress:wretch:xanga:xing:yahoo! answers:yahoo! bookmarks:yammer:yelp:youku:youtube:yuku:zinch".indexOf(':'+traffic.source+':') > 0 || socialMediaRegex.test(traffic.source)){ // Falta Social Source Referral | |
| channel = "Social"; | |
| } | |
| else if(traffic.medium == "email"){ | |
| channel = "Email" ; | |
| } | |
| else if(traffic.medium == "affiliate"){ | |
| channel = "Affiliates"; | |
| } | |
| else if(traffic.medium == "referral"){ | |
| channel = "Referral"; | |
| } | |
| else if(paidSearchRegex.test(traffic.medium)){ //Falta Ad Distribution Network | |
| channel = "Paid Search"; | |
| } | |
| else if(otherAdvertisingRegex.test(traffic.medium)){ | |
| channel = "Other Advertising"; | |
| } | |
| else if(displayRegex.test(traffic.medium)){ //Falta Ad Distribution Network | |
| channel = "Display"; | |
| } | |
| else{ | |
| channel = "(Other)"; | |
| } | |
| return channel; | |
| }; | |
| function setCookie(value, hostName, cookieName){ | |
| // Delete cookie | |
| document.cookie = cookieName+"=; expires=Fri, 31 Dec 1999 23:59:59 GMT; path=/; domain=" + hostName; | |
| // Set cookie | |
| var days = 30 * 6; // 6 months | |
| var date = new Date(); | |
| date.setTime(date.getTime()+(days*24*60*60*1000)); | |
| var expires = "; expires="+date.toGMTString(); | |
| document.cookie = cookieName+"="+value+expires+"; path=/; domain=" + hostName; | |
| } | |
| function get_top_domain(){ | |
| var i,h, | |
| weird_cookie='weird_get_top_level_domain=cookie', | |
| hostname = document.location.hostname.split('.'); | |
| for(i=hostname.length-1; i>=0; i--) { | |
| h = hostname.slice(i).join('.'); | |
| document.cookie = weird_cookie + ';domain=.' + h + ';'; | |
| if(document.cookie.indexOf(weird_cookie)>-1){ | |
| document.cookie = weird_cookie.split('=')[0] + '=;domain=.' + h + ';expires=Thu, 01 Jan 1970 00:00:01 GMT;'; | |
| return h; | |
| } | |
| } | |
| } | |
| var hostname = get_top_domain(); | |
| var traffic = getTrafficSource(hostname); | |
| var channel = traffic.channel; | |
| var source = traffic.source; | |
| var medium = traffic.medium; | |
| var gclid = traffic.gclid; | |
| var cid = traffic.cid; | |
| var device_category = traffic.device_category; | |
| setCookie(cid, hostname, cidCookieName); | |
| setCookie(gclid, hostname, gclidCookieName); | |
| setCookie(source, hostname, sourceCookieName); | |
| setCookie(medium, hostname, mediumCookieName); | |
| setCookie(channel, hostname, channelCookieName); | |
| setCookie(device_category, hostname, deviceCategoryCookieName); | |
| }catch(e){}; | |
| })(); |