How to track AJAX GET requests & PDF downloads with Google Analytics? - javascript

I'm retrieving content via a jQuery get Ajax call and add it to an element afterwards. The HTML code is added without any problem, just the JS code gets lost. What am I doing wrong? When I look at the response in Firebug it is still there, it's just not added to the HTML element.
My Ajax request:
function get_overlay_content(path)
{
$.get(path, function(data) {
$("#overlay_content").html(data).fadeIn(500);
$(function()
{
// do something
});
});
}
The response in Firebug:
<div id="imprint" class="overlay_box">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXX-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<div id="overlay_close" onclick="close_overlay();"><img src="/2012/images/overlay_close.png" id=""></div>
# ETC
The HTML after update:
<div id="overlay_content">
<div id="imprint" class="overlay_box">
<div id="overlay_close" onclick="close_overlay();"><img src="/2012/images/overlay_close.png" id=""></div>
<div class="overlay_heading"><img src="/2012/images/heading_download.png" height="65"></div>
# etc.
My guess is that it has something to do with encoding. What do you think?
Thanks!
Olaf
SOLVED:
Thanks to Uzi, the solution was quite simple, following the Google guide Asynchronous Tracking Usage Guide
But for everyone to understand: If you have one main file (index.html) from where you retrieve partials (lets call it /partials/_download_pdfs.html) via an AJAX GET request (e.g. jQuery.get()) all you have to do to track every AJAX request with Google Analytics is the following:
Add the tracking code for Analytics ABOVE the rest of your Javascript
and your AJAX GET request, put the following code in a callback function (if you don't put it in a callback it might slow down your actual request)
$.get(path_to_track, function(data) {
// Fade in effect:
$("#container").html(data).fadeIn(500);
// this part is interesting:
_gaq.push(['_setAccount', 'UA-XXX-1']);
_gaq.push(['_trackPageview', path_to_track]);
// Do other stuff in the callback
});
That's it. If you want to track PDF downloads on a page you retrieved with an AJAX GET request with jQuery (as I did), just add the following code to the partial (eg /partials/_download_pdfs.html)
<script type="text/javascript">
$(document).ready(function() {
$(".pdf_link").click(function(){
_gaq.push(['_setAccount', 'UA-XXX-1']);
_gaq.push(['_trackPageview', '/pdf/' + $(this).attr("id")]);
});
});
</script>

If I understand correctly, you are fetching HTML code using AJAX.
That block of code contains a script tag, and you expect the script to run one the request is complete.
Unfortunately it doesn't work this way, since as far as the DOM concerned, this is just an element.
I'm not sure why you need an AJAX code for google analytics to run, but in case it contains dynamic data, just make the AJAX call return the parameter you need and have a function running this code locally.

Related

How to track clicks on outbound links

[cross-posted on Google Products Forum http://productforums.google.com/d/topic/analytics/ZrB14a-6gqI/discussion ]
I am using the following code at http://www.cs.bris.ac.uk/Research/Algorithms/
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<script type="text/javascript">
function recordOutboundLink(link, category, action) {
try {
var myTracker=_gat._getTrackerByName();
_gaq.push(['myTracker._trackEvent', category , action ]);
setTimeout('document.location = "' + link.href + '"', 100)
}catch(err){}
}
</script>
which I just copied directly from http://support.google.com/analytics/bin/answer.py?hl=en&answer=1136920 .
However, it doesn't actually seem to report any clicks on the links where I have added onClick="recordOutboundLink(this, 'Outbound Links', 'Postdoc advert');return false;", for example. I have seen a number of complaints about this online but I haven't found a solution that works.
What am I doing wrong?
P.S. The closest related online complaint seems to be http://productforums.google.com/forum/#!topic/analytics/4oPBJEoZ8s4 which just claims the code is broken.
Here's what I'm using, which has been working for me. I'm using jQuery to add the onclick handler to any link with a class of "referral", but I'd expect adding it directly in the HTML to work as well.
$(function() {
$('.referral').click(function() {
_gaq.push(['_trackEvent', 'Referral', 'Click', this.href]);
setTimeout('document.location = "' + this.href + '"', 100);
return false;
});
});
edit: I believe your syntax for invoking a tracker by name is wrong. Since you aren't using a named tracker when you set up tracking at page load, you shouldn't try to name it later either. See the documentation for _gaq.push.
More precisely:
The var myTracker declaration is unused, so you can just delete that line. Variables declared within the scope of recordOutboundLink aren't visible when other functions, such as _gaq.push, are running, so it can't be relevant.
You should simply use '_trackEvent' instead of 'myTracker._trackEvent'.
You can also try this automated external link script
Set a longer timeout 2 seconds maybe, as it takes a certain amout of time for the _gaq.push to actually push to the server, and 100 milliseconds isnt long enough for it to send (the push gets cancelled as soon as the document.location changes). Unless _gaq.push uses a blocking call (doesnt execute the next line till the push is complete), but i dont think that is the case i think most of that uses asynchronous requests.

Load JavaScript dynamically [duplicate]

This question already has answers here:
JQuery to load Javascript file dynamically
(2 answers)
Closed 7 years ago.
I have a web page and a canvas with Google Maps embedded in it. I am using jQuery on this site.
I want to load Google Maps API only if the user clicks on "Show me the map". Further, I want to take away the whole loading of the Google Maps from the header in order to improve my page performance.
So I need to load JavaScript dynamically. What JavaScript function I can use?
You may want to use jQuery.getScript which will help you load the Google Maps API javascript file when needed.
Example:
$.getScript('http://maps.googleapis.com/maps/api/js?libraries=geometry&sensor=true', function(data, textStatus){
console.log(textStatus, data);
// do whatever you want
});
Use the Loading on Demand Loading Strategy
Loading on Demand
The previous pattern loaded additional JavaScript unconditionally after page load, assuming
that the code will likely be needed. But can we do better and load only parts of
the code and only the parts that are really needed?
Imagine you have a sidebar on the page with different tabs. Clicking on a tab makes an
XHR request to get content, updates the tab content, and animates the update fading
the color.
And what if this is the only place on the page you need your XHR and animation
libraries, and what if the user never clicks on a tab?
Enter the load-on-demand pattern. You can create a require() function or method that
takes a filename of a script to be loaded and a callback function to be executed when
the additional script is loaded.
The require() function can be used like so:
require("extra.js", function () {
functionDefinedInExtraJS();
});
Let’s see how you can implement such a function. Requesting the additional script is
straightforward. You just follow the dynamic element pattern. Figuring out
when the script is loaded is a little trickier due to the browser differences:
function require(file, callback) {
var script = document.getElementsByTagName('script')[0],
newjs = document.createElement('script');
// IE
newjs.onreadystatechange = function () {
if (newjs.readyState === 'loaded' || newjs.readyState === 'complete') {
newjs.onreadystatechange = null;
callback();
}
};
// others
newjs.onload = function () {
callback();
};
newjs.src = file;
script.parentNode.insertBefore(newjs, script);
}
“JavaScript Patterns, by Stoyan Stefanov
(O’Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750.”
you would just generate the script tag via javascript and add it to the doc.
function AddScriptTag(src) {
var node = document.getElementsByTagName("head")[0] || document.body;
if(node){
var script = document.createElement("script");
script.type="text/javascript";
script.src=src
node.appendChild(script);
} else {
document.write("<script src='"+src+"' type='text/javascript'></script>");
}
}
I think you're loking for this http://unixpapa.com/js/dyna.html
<input type="button" onclick="helper()" value="Helper">
<script language="JavaScript">
function helper()
{
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'your_script_url';
head.appendChild(script);
}
</script>
I used the Tangim response, but after found that is more easy use jquery html() function. When we make ajax request to html file that have html+javascript we do the follow:
$.ajax({
url:'file.html',
success:function(data){
$("#id_div").html(data); //Here automatically load script if html contain
}
});

detect and suppress errors loading javascript file

I want to source a javascript file from facebook http://connect.facebook.net/en_US/all.js
The organization I work for has a firewall that blocks access to Facebook, it just goes to an html page that says "Access Denied blah blah blah"
I want to be able to put a javascript src tag <script src="http://... "> </script> and detect and suppress the warnings when the browser tries to evaluate the html as javascript.
Anyone know how?
Looks like jQuery.getScript is what you need as was mentioned. Or you can manually execute:
$.ajax({
url: url,
dataType: 'script',
success: function(){document.write('<script src="http://... "> </script>');}
});
And append your html on successful load with the <script></script> tag.
With the standard <script> tag, not possible. There's nothing really running at the time when the script's src is hit and content downloaded, so you can't wrap that in a try/catch block. There's some tips here on how to dynamically load scripts. Maybe the browsers will add some stuff to the DOM element created there which you can check for.
This is a workaround, not a direct answer, but you could simply set up a reverse proxy outside the firewall for Facebook and load the script from there. Instead of failing more gracefully, it would allow the script not to fail.
Try this, and see if it works for you:
<script type="text/javascript" onerror="throw('An error occurred')" src="http://connect.facebook.net/en_US/all.js"></script>
Alternatively, if you have access to a proxy script to grab external content I would use it via an xmlHttpRequest to grab the JS content. If it is successful, eval the content (yes, eval is evil, I know).
I would add that if you know the JS will fail, then why bother?
Why do you not do this in very simple way?:
if(!window.FB) { // or (typeof window.FB === "undefined")
alert ("ERROR: http://connect.facebook.net/en_US/all.js is not loaded");
}
if(!window.jQuery) { // or (typeof window.jQuery === "undefined")
alert ("ERROR: jQuery is not loaded");
}
// and so on
Please try the function below, it will only call the onload_function if the script has loaded. You can set a timeout to cancel the script.
function include_js(url, onload_function) {
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) {
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
onload_function();
}
};
} else {
script.onload = function(){
onload_function();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
In Firefox and IE, you should be able to use window.onerror for this. You can take advantage of the fact that scripts run in the order they are listed in the HTML to wrap an error handler around just the facebook script:
<script>
// Remember old error handler, if there is one.
var oldOnError = window.onerror;
// Special error handler for facebook script
window.onerror = function(message, url, linenumber) {
// Potentially alert the user to problem
alert('Problem with facebook: ...');
// Return true to suppress default error handling
return true;
}
</script>
<!-- Load facebook script -->
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script>
// Remove error handler for facebook script
window.onerror = oldOnError;
</script>

Google Analytics Async Event Tracking

Wonder if somebody is able to clarify the following;
Using the aysnc google analytics code placed in the head of the document as follows
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-123456-1']);
_gaq.push(['_setDomainName', '.somedomain.co.uk']);
_gaq.push(['_trackPageview', pageUrl]);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
On some the pages I am tracking I also use custom events to track video plays and which forms are used. These events use a further _gaq.push() call at various points on the page.
My question is should the final section of the initial analytics code (the section that calls ga.js be split and placed at the end of the page code or will any calls made once the script has loaded still be passed to Analytics regardless of the position on the page.
Thanks in advance.
No, the final section of the initial analytics code need not be placed lower down. You can call as many _gaq.push() calls as you like throughout the page, they'll still successfully pass to analytics.
The _gaq.push() event calls will send new requests to Google Analytics in addition to the first one you make (_trackPageview). You can check those event calls my inspecting how many requests your page makes for _utm.gif in a tool like Firebug.

Loading scripts dynamically

I'm loading a few YUI scripts dynamically in my code in response to an Ajax request. The DOM and the page is fully loaded when the request is made - it's a response for an user event.
I add the <scripts> tag to head as children, but I stumbled in a few problems:
I add two YUI scripts hosted at the Yahoo! CDN and an inlined script of my own responsible for creating object, adding event listeners and rendering the YUI widgets. But I when my script run the YUI scripts are not loaded yet giving me errors and not running as I expect.
There's a way to only run my script (or define a function to be run) when YUI scripts are fully loaded?
Have you tried an onload event?
Edited:(thanks Jamie)
var script = document.createElement("script");
script.type = "text/javascript";
script.src = src;
//IE:
if(window.attachEvent && document.all) {
script.onreadystatechange = function () {
if(this.readyState === "complete") {
callback_function(); //execute
}
};
}
//other browsers:
else {
script.onload = callback_function; //execute
}
document.getElementsByTagName("head")[0].appendChild(script);
If you're using YUI 2.x I highly recommend using the YUI Get utility, as it's designed to handle just this sort of a problem.
If you are loading multiple individual script files from the Yahoo! CDN, you'll need to makes sure both are loaded before executing your dependent code. You can avoid this using the combo handler. See the Configurator to get what the script url should be to load both/all needed YUI files from one url.
http://developer.yahoo.com/yui/articles/hosting/
With that in mind, assuming you must load the YUI files asynchronously, you should use an onload/onreadystatechange handler as noted by digitalFresh.
I would recommend the following pattern, however:
(function (d) {
var s = d.createElement('script'),
onEvent = ('onreadystatechange' in s) ? 'onreadystatechange' : 'onload';
s[onEvent] = function () {
if (("loaded,complete").indexOf(this.readyState || "loaded") > -1) {
s[onEvent] = null;
// Call your code here
YAHOO.util.Dom.get('x').innerHTML = "Loaded";
}
};
// Set the src to the combo script url, e.g.
s.src = "http://yui.yahooapis.com/combo?2.8.1/...";
d.getElementsByTagName('head')[0].appendChild(s);
})(document);
You could use a setTimeout() to run some function that just checks if it's loaded - check something like
if (typeof YUI_NAMESPACED_THING !== "undefined") runCode()
EDIT Thanks, CMS
If I understand this correctly, your ajax response with this:
<script href="yui-combo?1"></script>
<script href="yui-combo?2"></script>
<p>some text here</a>
<script>
// using some of the components included in the previous combos
// YAHOO.whatever here...
</script>
If this is the case, this is a clear case in which you should use dispatcher plugin. Dispatcher will emulate the browser loading process for AJAX responses. Basically it will load and execute every script in the exact order.
Best Regards,
Caridy

Categories

Resources