Profile cover photo
Profile photo
Carmen Mardiros
Hands-on analytics "jack of all trades"
Hands-on analytics "jack of all trades"


Got a very odd problem. Have noticed that for a small number of hits we send to UA we end up with "bits" of data in the wrong dimensions in UA. Like a corrupted hit.

For example we send a timestamp in cd8, this sometimes gets shifted in another place, sometimes where pagePath is, sometimes in another place. It's like those annoying times you have an extra comma in a CSV which shifts the row in Excel but way more inconsistent, I'm wondering if something similar is happening with the request URL.

But what's even weirder is that I'm seeing GTM/JS-related stuff being sent along with the request, for example I have a tag that does some DL enrichment and then does a push to the DL with the event 'done_enrich_data_layer' and enriched keys.

This value (done_enrich_data_layer) somehow ends up randomly in various dimensions. Also seeing [object Object], undefined etc. Almost like GTM did not parse the code properly or somehow the dataLayer push itself got corrupted and the corrupted values are just passed downstream to the UA tag.

Very annoying and at a loss how to debug as I can't reproduce it and the entire data associated with that hit seems to be corrupted.

First thought is maybe we're not escaping the different "parts" of the URL request properly (we're sending full path, incl query params and fragment). But as the request seems to be sent as key, value pairs, this seems unnecessary. Also doesn't seem to explain the JS/GTM event names that end up in UA.

Has anyone seen anything like this before? Especially GTM-related "bits" ending up in the request, and therefore in UA? Any suggestions how to proceed to debug?


I'm wondering how other people are identifying expensive macros and tags (those that take a long time to execute). Also, I'm interested in what other people consider to be "expensive".

For tags, I push a timestamp to the data layer as the final step of the execution and I compare this with the timestamp of previous tags or the timestamp associated with the gtm.js event. I have one tag which manipulates some of the data layer contents and this finishes about 700ms after gtm.js timestamp. Would people consider this expensive?

I also have a HTML tag that creates a GA tracker object and finishes execution 2s after gtm.js which seems like a lot (this is all measured in debug mode by the way).

But I don't have a good way to measure expensive macros and can't work out if debug mode offers anything to help with that. Any ideas?

Post has attachment
indexOf is very useful when writing custom JS but seems browser support is not extensive:

What robust alternatives are people using?

Curious how other people QA their GTM setup (custom javascript et all) works on mobile/tablet (various browsers). I've played with Remote debugging on Android but obviously this is one browser on one OS. 


I had an interesting debate the other day. What is more beneficial to an organisation, a handful of 100% fully dedicated analysts or everyone in the company spending 20% of their time doing analysis confidently and in a self sufficient manner (or both?).

The answer will of course vary from organisation to organisation and there are obvious pros and cons to each one.

One argument presented for "100% analysts" is that being able to carry out analysis is not everyone's competency and may actually detract from their core strengths.

One argument presented for the "everyone doing 20% analysis" is much shorter feedback loops between asking and answering the business question as this happens within the same person, and possibly an initial greater understanding of the business question being asked.

I wanted to hear what other people working in data and analytics think, what they've seen work and not work and in what types of organisation.

+Peter O'Neill +Stéphane Hamel +Yehoshua Coren +Doug Hall +Yali Sassoon +Craig Sullivan +Daniel Waisberg +Gary Angel +John Woods +Jono Alderson +Jim Sterne 
Add a comment...

Post has shared content

Wrote a series of posts to accompany my Measurecamp presentation on the Lego Data Layer (work in progress). Thought this might be of interest to GTM folks:

Post has shared content
Oh CNN ... "This math is hard..."
Add a comment...

Morning GTM community! This post is about traversing the DOM to find the logical parent of an element.

We all know DOM traversal is fragile and that if you can capture the interaction and its context server side/ajax, then that's definitely the way forward. However, that won't work for client side only interactions (ie vanilla clicks) -- unless I'm missing something really obvious.

Take Enhanced eCommerce for example. Tracking clicks on products in a list requires that at the moment of the click you are able to uniquely identify the location of the product on the page (the "product list" the product is in) so that you can assign the click to the right list. For scenarios where there is ever only one list of products on the page we can use the page itself (and therefore a server-side generated data layer) as the "where" context. But there's an increased need to capture the "where" context at the more granular level of "where within a page". This is where DOM traversal comes in, fragile as it is.

I've recently noticed that form fields and forms have a built in parent - child relationship. So when someone interacts with a form field you can use  .form (note the dot) to get the parent form the field belongs to (no matter how deeply it's buried in divs). You can then get the name, id etc of the form using dot notation like this: {{element}} This means we can safely associate events on field "email address" found in 2 different forms (register, login).

I was thinking it would be awesome if there were other html elements with built in parent - child relationships that would work in the same way. For ecommerce, the idea would be to wrap products (the children) under such a parent element and to use dot notation to access a product's logical parent directly (NOTE: logical parent is NOT the same as parentNode). I did some research but couldn't find any other such element pairs.

Another option would be to identify the logical parent element and explicitly tag it with HTML5 dataset attributes to effectively say "this element is the de facto parent of the element you've just interacted with". But this still involves DOM traversal. However, because it uses dedicated HTML5 dataset attribute that has no role in presentation, it might not be as fragile (let's debate this point as it's worthy of discussion).

I can see other use cases like:

* Multiple calls to action found within different in-page content tabs (you want to identify which call to action in which tab was most effective).

* Product snippets which are effectively a container for multiple possible interactions (click on image, click to wishlist, click on reviews, etc), all needing to be associated with a specific product sku/name.

A non DOM traversal solution would involve tagging all of those elements with the product id, product name, etc so that they're available using {{element}}.attribute dot notation. This feels ugly, inelegant and repetition breeds human error. The above alternative seems like a good compromise, but I'd love to hear other thoughts and approaches, especially if you disagree!

Here is how I do it for products in lists:

I tag the <ul> element (which often denotes the product category) with HTML5 markup: <ul data-entity="product collection" data-product-collection-name="shirts">

I tag the <li> element (which denotes the product snippet) with HTML5 markup: <ul data-entity="product" data-product-name="beautiful blue shirt">

Then when someone clicks on something within the product snippet (buried inside the <li>), I have these two custom JS macros:

{{element - dataset - parent entity - product collection}}:

function() {
    var parent = {{element}}.parentElement;
    var entity = parent.getAttribute('data-entity');
    while (entity !== 'product collection') {
      parent = parent.parentElement;
      entity = parent.getAttribute('data-entity');
    return parent;

{{element - dataset - parent entity - product}}:

function() {
    var parent = {{element}}.parentElement;
    var entity = parent.getAttribute('data-entity');
    while (entity !== 'product') {
      parent = parent.parentElement;
      entity = parent.getAttribute('data-entity');
    return parent;

These return the <ul> and <li> elements belonging to parent product collection and product respectively

I then use additional JS macros which extract attributes from these parents:

{{element - dataset - parent entity - product - name}} //this gets the product name

function() {
    return {{element - dataset - parent entity - product}}.getAttribute('data-product-name');

{{element - dataset - parent entity - product collection - name}} //this gets the product list name

function() {
    return {{element - dataset - parent entity - product collection}}.getAttribute('data-product-collection-name');

A simple logger to console shows what data becomes available to GTM when someone clicks on any element inside the product snippet:

// element - dataset - parent entity - product collection: ul.products-grid.products-grid--max-4-col.first.last.odd
// element - dataset - parent entity - product collection - name: Books & Music

// element - dataset - parent entity - product: li.item.first
// element - dataset - parent entity - product - name: Alice in Wonderland

So, this is still DOM traversal but it feels much more controlled and less fragile thanks to the dataset markup and the fact that parent seeking is limited to a specific kind of parent.

What I haven't measured (and no idea how to do this) is how expensive this DOM traversal is when product collection and product don't exist on the page.


cc: +Simo Ahava , +Doug Hall , +Stephane Hamel , +Phil Pearce 

Post has attachment
Friday GA geekery for Mac users:

Preamble: If you're not using Alfred you're nuts. 

Here's an Alfred workflow to quickly browse all of the GA API metrics and dimensions straight from your keyboard. I simply bring up Alfred and start typing...

- API expression
- UI name
- whether metric or dimension
- whether allowed in segments
- whether deprecated/public

Hitting Enter copies its API expression to clipboard. Handy for pasting in the Data Feed Explorer or constructing API expressions.

Video and Download link:

And more about Alfred: (you need the PowerPack version to install the workflow)
Wait while more posts are being loaded