In many cases it could be interesting to store raw tracking data on hit level besides the pre-processed reports available in the Analytics web interface in order to be able to perform a deeper analysis on this kind of raw data. While Google Analytics Premium offers the feature of Bigquery export, no comparable functionality is available in the free Google Analytics version - at least not out of the box.
With the following solution, Analytics hits (tracking requests) can be duplicated and sent to your own server endpoint, so you can store them in a log file or a database for further analysis. Therefore you also gain access to raw tracking data (even in realtime) with the free Analytics version.
In order to send the data also to your own server, the following JavaScript code can be used - an own version of the sendHitTask function, which sends the Measurement Protocol tracking request to the Google Server and your own server endpoint.
function sendHitTask(){ return function(model) { var payLoad = model.get('hitPayload'); var trackingBaseUrls = ['//www.google-analytics.com/collect?', '//www.own-server.com/ownEndpoint?']; for (i = 0; i < trackingBaseUrls.length; i++) { if (payLoad.length < 400) { var collectUrl = window.location.protocol + trackingBaseUrls[i] + payLoad; var myImage = new Image(); myImage.src = collectUrl; } else { var r = window.ord || Math.floor(Math.random() * 1e16); var myIframe = document.createElement('IFRAME'); myIframe.width = "1px"; myIframe.height = "1px"; myIframe.style.display = 'none'; myIframe.name = "tiframe_" + r; var myForm = document.createElement('FORM'); myForm.method = 'POST'; myForm.action = window.location.protocol + trackingBaseUrls[i]; myForm.target = "tiframe_" + r; var parameterValuePairs = payLoad.split('&'); for (var vpi=0; vpi < parameterValuePairs.length; vpi++) { var splittedParameterValuePair = parameterValuePairs[vpi].split('='); var parameterName = decodeURIComponent(splittedParameterValuePair[0]); var parameterValue = (splittedParameterValuePair.length == 1) ? '' : decodeURIComponent(splittedParameterValuePair[1]); var parameterInput = document.createElement('INPUT'); parameterInput.type = 'HIDDEN'; parameterInput.name = parameterName; parameterInput.value = parameterValue; myForm.appendChild(parameterInput); } document.body.appendChild(myForm); document.body.appendChild(myIframe); myForm.submit(); } } }; }
Alternative method using AJAX:
function sendHitTask(){ return function(model) { var payLoad = model.get('hitPayload'); var trackingBaseUrls = ['//www.google-analytics.com/collect', '//my-endpoint/tracker']; for (i = 0; i < trackingBaseUrls.length; i++) { var baseUrl = window.location.protocol + trackingBaseUrls[i]; if (payLoad.length < 400) { var collectUrl = baseUrl +'?'+ payLoad; var myImage = new Image(); myImage.src = collectUrl; } else { var req = Xhr(); if(req != null){ req.open('POST', baseUrl, true);
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); req.send(payLoad); } } } }; function Xhr(){ try { return new XMLHttpRequest(); }catch(e){} try { return new ActiveXObject("Msxml3.XMLHTTP"); }catch(e){} try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }catch(e){} try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }catch(e){} try { return new ActiveXObject("Msxml2.XMLHTTP"); }catch(e){} try { return new ActiveXObject("Microsoft.XMLHTTP"); }catch(e){} return null; } }