3

Update: an interesting article on this topic by YannisG: http://digitalinsightsworld.com/tag-manager/push-datalayer-values-adobe-sitecatalyst-variables-via-dtm/

There is a website with Google Tag Manager and dataLayer installed. I want to try another tag management solution (Adobe DTM) using the same dataLayer, so no more development is needed.

The dataLayer is a list of objects. One of the objects contains "pageview" property, which I want to send to Adobe Analytics on all pageviews.

Object {
event: "virtual PV",
pageview: "/page1",
__proto__: Object}

Let's say I want to get the pageview property from one of the dataLayer's objects and put it into Adobe Analytics "prop1" variable.

What I did in Adobe DTM:

  1. set a custom data element "dataLayer - pageview - page1" as custom script (the script returns a string "/page1", which should be added as "prop1" to Adobe Analytics:

    var result = dataLayer.filter(function( obj ) {
        return obj.event == 'virtual PV';
        });
    return result[0].pageview
    
  2. set a page load rule (launched at DOM ready) and set "prop1" variable as: %dataLayer - pageview - page1%.

prop1="%dataLayer - pageview - page1%"

In theory this setup should work and every pageview should have a prop1 = "/page1", however in the console I see the error:

SATELLITE: TypeError - Cannot read property 'pageview' of undefined

What could be the reason? When I type the data element code in the console - it gets the pageview value correctly. Maybe the GTM's dataLayer object is not ready, when DTM wants to extract data from it, so I should delay DTM - but how?

chilliq
  • 1,212
  • 3
  • 13
  • 32
  • Where does this data layer live on the page? Remember, DTM is loaded synchronously- which means it loads from top to bottom and the UI data elements are usually set early in the page load. If your data layer is loaded asynchronously or isn't available until later then your data elements, scripts or variables will return undefined – Mark Stringham Mar 31 '16 at 19:08
  • The dataLayer is a standard GTM dataLayer object, initialized together with main GTM code (just beneath opening ). The DTM prop1 rule is set to launch at "DOM Ready", so I guess the dataLayer should be created by then. Am I wrong about it? – chilliq Apr 06 '16 at 21:03
  • I recognize that you've stated that the GTM dataLayer is initialized just beneath the opening , but when is the "virtual PV" object pushed onto the data layer? – Aaronius Jun 01 '18 at 03:21

1 Answers1

3

Use Data Layer Helper

Wonderful library designed for this purpose: https://github.com/google/data-layer-helper

It works very same like GTM dataLayer, but you can design it by you own.

It is fully asynchronous!

How to use it?

Implement this library:

(function(){/*
 jQuery v1.9.1 (c) 2005, 2012
 jQuery Foundation, Inc. jquery.org/license.
*/
var g=/\[object (Boolean|Number|String|Function|Array|Date|RegExp)\]/;function h(a){return null==a?String(a):(a=g.exec(Object.prototype.toString.call(Object(a))))?a[1].toLowerCase():"object"}function k(a,b){return Object.prototype.hasOwnProperty.call(Object(a),b)}function m(a){if(!a||"object"!=h(a)||a.nodeType||a==a.window)return!1;try{if(a.constructor&&!k(a,"constructor")&&!k(a.constructor.prototype,"isPrototypeOf"))return!1}catch(b){return!1}for(var c in a);return void 0===c||k(a,c)};/*
 Copyright 2012 Google Inc. All rights reserved. */
function n(a,b,c){this.b=a;this.f=b||function(){};this.d=!1;this.a={};this.c=[];this.e=p(this);r(this,a,!c);var d=a.push,e=this;a.push=function(){var b=[].slice.call(arguments,0),c=d.apply(a,b);r(e,b);return c}}window.DataLayerHelper=n;n.prototype.get=function(a){var b=this.a;a=a.split(".");for(var c=0;c<a.length;c++){if(void 0===b[a[c]])return;b=b[a[c]]}return b};n.prototype.flatten=function(){this.b.splice(0,this.b.length);this.b[0]={};s(this.a,this.b[0])};
function r(a,b,c){for(a.c.push.apply(a.c,b);!1===a.d&&0<a.c.length;){b=a.c.shift();if("array"==h(b))a:{var d=b,e=a.a;if("string"==h(d[0])){for(var f=d[0].split("."),u=f.pop(),d=d.slice(1),l=0;l<f.length;l++){if(void 0===e[f[l]])break a;e=e[f[l]]}try{e[u].apply(e,d)}catch(v){}}}else if("function"==typeof b)try{b.call(a.e)}catch(w){}else if(m(b))for(var q in b)s(t(q,b[q]),a.a);else continue;c||(a.d=!0,a.f(a.a,b),a.d=!1)}}
function p(a){return{set:function(b,c){s(t(b,c),a.a)},get:function(b){return a.get(b)}}}function t(a,b){for(var c={},d=c,e=a.split("."),f=0;f<e.length-1;f++)d=d[e[f]]={};d[e[e.length-1]]=b;return c}function s(a,b){for(var c in a)if(k(a,c)){var d=a[c];"array"==h(d)?("array"==h(b[c])||(b[c]=[]),s(d,b[c])):m(d)?(m(b[c])||(b[c]={}),s(d,b[c])):b[c]=d}};})();

And then init the helper object.

function listener(message, model) {
  // Message has been pushed. 
  // The helper has merged it onto the model.
  // Now use the message and the updated model to do something.
}
var helper = new DataLayerHelper(dataLayer, listener, true);

Message

Each message equals dataLayer.push. It is an object valid only inside listener callback.

Model

Model keeps constantly updated model of all dataLayer information sended. It is updated on every listeners iteration.

Model is updated by message.

Your case

function listener(message, model) {

   if(message.event == "Virtual PV"){
       s.prop1=model.page;
       s.t();
   }

}
var helper = new DataLayerHelper(dataLayer, listener, true);
Jakub Kriz
  • 1,501
  • 2
  • 21
  • 29
  • 1
    This seems to be a great tool to create platform independent dataLayer, which is probably what I need, if it works in this case. Do you think if it's possible to use this library through GTM (avoiding additional development would be a big +)? I'm going to give it a try and come back with some insights :) – chilliq Apr 06 '16 at 20:58
  • @chilliq - Yes, it is platform independent and you can create very custom trackers with it. It is internal part of GTM, so I don't recommend you to implement it again into same system. But if you put it into DTM, it definitely works perfect! I build up tens of custom trackers with this helper. – Jakub Kriz Apr 07 '16 at 08:06