1
\$\begingroup\$

I've researched this morning how to use Google Analytics to track outbound page views. However, I think the implementation might be a bit difficult on our website (as we have hundreds of outbound links)

Here's what google recommends.

/**
* Function that tracks a click on an outbound link in Analytics.
* This function takes a valid URL string as an argument, and uses that URL string
* as the event label. Setting the transport method to 'beacon' lets the hit be sent
* using 'navigator.sendBeacon' in browser that support it.
*/
var trackOutboundLink = function(url) {
   ga('send', 'event', 'outbound', 'click', url, {
     'transport': 'beacon',
     'hitCallback': function(){document.location = url;}
   });
}
<a href="http://www.example.com" onclick="trackOutboundLink('http://www.example.com'); return false;">Check out example.com</a>

As you can see, attaching an onClick attribute to every single anchor tag you want to track is fine, IF YOU ARE JUST NOW DEVELOPING A WEBSITE!

To remedy this issue, I have written some code to loop through every anchor tag on the page, and determine if the anchor is external or not. In this script, *.pdf need to be included. Here my custom script:

var anchors = document.getElementsByTagName("a");
		
		for (i = (anchors.length - 1); i > -1; i--) {
			var anchorHREF = anchors[i].getAttribute("href");
			if (anchorHREF != "" && anchorHREF != null) {
				var doSetOnClick = false;
				
				if (anchors[i].hostname != document.location.hostname) {
					doSetOnClick = true;
				}
				
				if (anchorHREF.indexOf(".pdf") > -1) {
					doSetOnClick = true;
				}
				
				if (doSetOnClick) {
					anchors[i].setAttribute("onClick", "javascript: trackOutboundLink('" + anchorHREF + "');")
				}			
			}
  }

Note: This code fires on DOM Ready.

I am not asking for code review on the google part, just my custom loop. Do you feel as though my loop is going to have good browser support? >IE8? How could I Improve this code?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I would write this code like:

Array.prototype
  .slice
  .call(document.getElementsByTagName("a")) // Get all links from the page
  .forEach(function (link) { // Loop through them
    const isExternal = link.hostname != document.location.hostname;  // Check if is external
    const isPDF = link.href.indexOf(".pdf") > -1; // Check is is PDF
    if(isExternal || isPDF){
      link.setAttribute("onClick", "javascript: trackOutboundLink('" + link.href + "');"); // set onClick attribute
    }
  })

Update #1

Using ES6, you can do something like this:

// Get all the links from the page
const links = [...document.getElementsByTagName('a')];

// "Explain what a pdf link is"
const isPDF = link => link.href.endsWith('.pdf');

// "Explain what an external is"
const isExternal = link => link.hostname != document.location.hostname;

// "Explain what links you want to target"
const target = link => isPDF(link) || isExternal(link);

// "Explain what should be done to those links"
const onClick = link => link.setAttribute('onClick', `javascript: trackOutboundLink('${link.href}');`);

// Filter and do the work
links.filter(target).map(onClick);

I would suggest the second method, because it's much more clear, pure and very easy to test.

\$\endgroup\$
2
  • \$\begingroup\$ Since you've provided an ES6 solution you could probably use String.prototype.endsWith over indexOf to check if the file is a pdf \$\endgroup\$
    – Craig Ayre
    Commented Feb 28, 2017 at 9:27
  • \$\begingroup\$ No worries! A few more things while I'm here: You could provide a spread operator alternative to Array.from and setAttribute could use string templates: `javascript: trackOutboundLink("${link.href}");`(and to be real picky onClick could be in single quotes to be consistent) - Nice work! \$\endgroup\$
    – Craig Ayre
    Commented Feb 28, 2017 at 9:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.