Challenges Surrounding Analytics Tagging
maigi / 123RF Stock PhotoI am often asked if TagManager can be used to tag a particular site.  It seems easy.  If we can get a reference to the JavaScript on all the pages, is it possible to setup all the data collection for the entire site from that reference?  It’s an interesting proposition.  Some customers comment that SiteCatalyst and the entire Digital Marketing Suite’s implementation can be painful.  Some customers remark that it can be cumbersome and often involves a huge investment of time and effort for simple changes.  Fortunately, there are a handful of tools that have been put in place to address these issues.  The introduction of new features such as processing rules and context data variables make implementing data collection much easier.

Enter Tag Manager
TagManager is probably the most powerful compliment to that toolset, but still the standard way of surfacing data on the page through JavaScript creates a higher bar of implementing.  Often when data is surfaced on the page in JavaScript rather than HTML it requires a developer to do the work, as well as a higher level of acceptance testing than is required with HTML.  HTML doesn’t execute so the risks are inherently lower.  This got me thinking:  what if we used only HTML for tagging?  After all, the Document Object Model is based on Object-Oriented programming paradigms.  It should be possible to make the D in DOM responsible for its own data.

The Challenge: JavaScript-Free Tagging
So as a challenge, I decided to assemble a brand new, pie-in-the-sky approach to tagging.  What would JavaScript-free tagging look like?  How would we approach it from a development aspect and make it supportable and responsive to marketing needs?  Here are the requirements for this challenge:

  1. The implementation should be loosely coupled.  If an element is removed from the page accidentally it shouldn’t create a JavaScript error.
  2. The page should effectively “listen” for data.  This includes responding to event-triggered tagging as well and page-driven tagging.
  3. The order of operation should be irrelevant.  That is, a JavaScript file declared at the top page versus the bottom of the page should make no difference.  In the end we need data regardless of the execution order.
  4. Data should only be and always be HTML.

An Example:
Let’s begin with an example of a simple HTML page. On any page I have lots of data. Let’s suppose we are discussing a product page that has a picture of the product with a name as well as a cart icon somewhere that indicates the number of items in the cart among numerous other items.  Bottom-line:  there’s an incredible amount of data on every page before ever tagging anything.  All of this data can potentially be used to populate tagging variables.  You can write a simple JavaScript line to pull the innerHTML from the </h1> tag and instantly you have a usable pageName. But what happens when the web developer changes the </h1> tag to </h2>?  Just as quickly as you created a solution, the change has caused it to stop functioning!

Instead of looking for particular HTML elements, let’s instead leverage the class attribute to indicate that the </h1> or </h2> elements are data.  In this way, we can look for an identifier such as “ATM” to indicate that the item is data and we don’t need to rely on the element type, which may change over time.

For example, with the page below we can use simple JavaScript (document.getElementsByClassName) to grab all the data points.  Easy right?

<html>
<body>
<h1 class="ATM">My Title</h1>
<div>Widget<div>
</body>
<html>

So, how do we know what to do with that data?  Does the <h1> class go into page name?  Does the <div> class go into the products variable?  Ok, so it’s not quite that simple. We have a few more things to do.  Since we know that the two elements above contain data, let’s now figure out how to understand where the data should live.  The “id” attribute has a similar function.  The variable name (prop1, eVar4, etc.) should be unique to the page.  In our example then, let’s add an id.

<html>
<body>
<h1 id="title">My Title</h1>
<div id="products" class="ATM">Widget<div>
</body>
<html>

We now have 2 data elements that we will use to collect data: title and products.  Effectively, we have data collection similar to the following without using any declared JavaScript variables:

s.pageName = "My Title"
s.products = ";Widget";

Let’s now take a look at the listening requirement.  As I mentioned, from the JavaScript file or tag container we can now query all the elements that contain the class “ATM”, which is easy enough.  Something like the following will collect our elements.

var elements = document.getElementsByClassName('ATM');
for(var i in elements) {
....
}

Within this loop we can then put the elements with the id ‘title’ in s.pageName and the element with the id ‘products’ in s.products.  This is not all that difficult.  What can be difficult is knowing at what point all the data is there. After all, my page can do asynchronous requests for HTML and return within that string extra data about the page.  How do we account for this?

One option might be to use jQuery’s $(document).ready().  The jQuery library is a fairly well used library and even if you aren’t using it on your site, it is fairly easy to include within your tag container.  To use jQuery, we would wrap the code above in the $(document).ready() function like this:

$(document).ready(function () {
var elements = document.getElementsByClassName('ATM');
for(var i in elements) {
....
}
});

If you do not want to include jQuery in your solution you can approach this problem differently.  One suggestion is to create an HTML element with the sole purpose of indicating that the data is ready on the page.  Essentially, we would have a DOM element that resembles this:

<span class="ATM" id="ready"></span>

With this element you can asynchronously surface data in the DOM without concern for the order of execution.   The code for this might look something like this:


s.wait = setInterval("s.isComplete()", 200);
s.isComplete = function() {
var n = 0;
if(document.getElementById('complete')) {
clearInterval(this.wait);
this.ready();
} else if(n++ == 5) {
clearInterval(this.wait);
}
};
s.ready=function(s,p){
var a = document.getElementsByClassName('ATM');
for(var i = 0; i<a.length;i++) {
var v = a[i].id;
if(v != 'complete')
s[v] = a[i].innerHTML;
}
};

Review: Does it Satisfy the Four Key Requirements?
To review, we have data being set in HTML with tags and not JavaScript variables.  We have at least one HTML element that is indicating that the data is ready.  Finally we have JavaScript waiting for the HTML or data to be ready.  Let’s see if we’ve created something that satisfies our four basic requirements.

  1. Loosely Coupled Implementation: We have created a way of surfacing data on the page that is loosely coupled.  We can add these elements and without any form of data collection there will be no errors.  If the HTML element serves no visual purpose we can make it hidden and we are no worse for the wear.  HTML is just mark up.  It’s either rendered on the page, hidden, or contains a reference to another asset, but it doesn’t execute, which means there is no potential for JavaScript errors.
  2. Page Listens For Data: With the JavaScript above, we are effectively listening for the page data.  When the complete element is loaded, the JavaScript will pull all the data elements and send the request.
  3. No Order of Operations Dependencies: We’ve made the load order irrelevant.  The JavaScript can be loaded at the top of the page or bottom – before the data elements or after.  It really doesn’t matter.
  4. HTML Only – No JavaScript: We are certainly only using HTML – no doubt about that.

The result is a very basic, but powerful solution for using TagManager to tag your pages using the data that is already on them. I would love your feedback.  Is this a good idea or bad idea?  Does this make tagging easier?  What do you think is missing?  Feel free to add your comments below.

0 comments