Enhanced logging for Direct Call Rules and Custom Events for Launch/DTM

33 Sticks Logo- Orange Circle with 3|3 in it

(This is cross-posted from the 33 Sticks blog)

UPDATE: The wonderful devs behind Adobe Launch have seen this and may be willing to build it in natively to the product. Please go upvote the idea in the Launch Forums!

As discussed previously on this blog, Direct Call Rules have gained some new abilities so you can send additional info with the _satellite.track method, but unfortunately, this can be difficult to troubleshoot. When you enabled _satellite.setDebug (which should really probably just be called “logging” since it isn’t exactly debugging) in DTM or Launch, your console will show you logs about which rules fire. For instance, if I run this JavaScript from our earlier blog post:

_satellite.track("add to cart",{name:"wug",price:"12.99",color:"red"})

I see this in my console:

Or, if I fire a DCR that doesn’t exist, it will tell me there is no match:

Unfortunately, this doesn’t tell me much about the parameters that were passed (especially if I haven’t yet set up a rule in Launch), and relies on having _satellite debugging turned on.

Improved Logging for Direct Call Rules

If you want to see what extra parameters are passed, try running this in your console before the DCR fires:

var satelliteTrackPlaceholder=_satellite.track //hold on to the original .track function
_satellite.track=function(name,details){ //rewrite it so you can make it extra special
   if(details){
      console.log("DCR NAME: '"+name+"' fired with the following additional params: ", details)
   }else{
      console.log("DCR NAME: '"+name+"' fired without any additional params")
   }
   //console.log("Data layer at this time:" + JSON.stringify(digitalData))
   satelliteTrackPlaceholder(name,details) //fire the original .track functionality
}

Now, if I fire my “add to cart” DCR, I can see that additional info, and Launch is still able to run the Direct Call Rule:

You may notice this commented-out line:

//console.log("Data layer at this time:" + JSON.stringify(digitalData))

This is for if you want to see the contents of your data layer at the time the DCR fires- you can uncomment it if that’d also be helpful to you. I find “stringifying” a JavaScript object in console logs is a good way of seeing the content of that object at that point in time- otherwise, sometimes what you see in the console reflects changes to that object over time.

Improved Logging for “Custom Event”-Based Rules

If you’re using “Custom Event” rules in DTM or Launch, you may have had some of the same debugging/logging frustrations. Logs from _satellite.setDebug will tell you a rule fired, but not what extra details were attached, and it really only tells you anything if you already have a rule set up in Launch.

For example, let’s say I have a link on my site for adding to cart:

Add To Cart!

My developers have attached a custom event to this link:

var addToCartButton = document.getElementById("cartAddButton"); 
addToCartButton.addEventListener("click", fireMyEvent, false); 
function fireMyEvent(e) { 
   e.preventDefault(); 
   var myCustomEvent = new CustomEvent("cartAdd", { detail: { name:"wug", price:"12.99", color:"red" }, bubbles: true, cancelable: true }); 
   e.currentTarget.dispatchEvent(myCustomEvent)
}

And I’ve set up a rule in Launch to listen to it:

With my rule and _satellite.setDebug in place, I see this in my console when I click that link:

But if this debugging doesn’t show up (for instance, if my rule doesn’t work for some reason), or if I don’t know what details the developers put on the custom event for me to work with, then I can put this script into my console:

var elem=document.getElementById("cartAddButton")
elem.addEventListener('cartAdd', function (e) { 
  console.log("'CUSTOM EVENT 'cartAdd' fired with these details:",e.detail)
}, false);

Note, you do need to know what element the custom event fires on (an element with the ID of “cartAddButton”), and the name of the event (“cartAdd” in this case)- you can’t be as generic as you can with the Direct Call Rules.

With that in place, it will show me this in my console:

Note, any rule set up in Launch for that custom event will still fire, but now I can also see those additional details, so I could now know I can reference the product color in my rule by referencing “event.detail.color” in my Launch rule:

Other tips

Either of these snippets will, of course, only last until the DOM changes (like if you navigate to a new page or refresh the page). You might consider adding them as code within Launch, particularly if you need them to fire on things that happen early in the page load, before you have a chance to put code into the console, but I’d say that should only be a temporary measure- I would not deploy that to a production library.

What other tricks do you use to troubleshoot Direct Call Rules and Custom Events?

Get the most out of DTM for deploying Third Party Tracking

One of the benefits of using a tag management system like DTM is the ability to lighten the load on your page by moving tracking pixels into DTM. Now, simply moving code into DTM may not improve page performance- there are best practices you need to follow to get the most out of what DTM can offers.

1. Decide on the scope

When the DTM library loads, it defers as much code as possible to later in the page. In order to map out what should run where it must run through each of your rule conditions and see which conditions are currently met. That means that additional rules and additional conditions will actually slow down the synchronous part of your DTM library. When possible, don’t create a new rule for each new tag, but rather, have rules be specific to their condition. I have a partner post about how to improve page performance when planning out your rules, but for now, try to start thinking of your rules in terms of the user action- have one rule for when the user sees a product details page, for example, rather than a series of Product Details Page rules, each with a different tag.

2. Decide which type of DTM script to use

Since 3rd party Tag vendors generally deliver their code in HTML form, intended to be pasted directly into your page, there are usually a few changes you need to make before DTM can fire the code non-sequentially.  What you do varies by the tag.
Before proceeding, you need to decide: should you use non-sequential HTML or non-sequential javascript? DTM loads non-sequential HTML by setting it in a side <iframe> so it can load the content without blocking anything else. This can work well, but has some downsides: that iframe can’t get all the same information the parent page can. This includes many data elements- for security reasons, it can’t reference a data element that pulls from Custom JS or JS objects. If you’re referencing a data element, you need to use “%dataElementName%” rather than “_satellite.getVar(“dataElementName”)”. This isn’t the most supported usage, so definitely test it thoroughly.

3. Remove unneeded pieces

Next, remove any <noscript> tags: they won’t do any good in a Javascript-based framework like DTM. These days, these tags aren’t really needed and may actually inflate your data because the only folks who don’t have JavaScript enabled are bots.

4. Convert the code to suit your script type

Next, convert the code to the appropriate format (see below) and add it in a rule as a Third Party Tag.

Purely Script

Some tags are already just javascript. For instance, take this code from facebook:

<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','//connect.facebook.net/en_US/fbevents.js');

fbq('init', '123456789123');
fbq('track', 'PageView');
</script>

<noscript>
<img height=""1"" width=""1"" style=""display:none""
src=""https://www.facebook.com/tr?id=1552630471664132&ev=PageView&noscript=1""
/></noscript>

<!-- End Facebook Pixel Code -->

I would remove the <script> tags, the <noscript> portion, and HTML comments, and paste it directly as JavaScript:

!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
 n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
 n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
 t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
 document,'script','//connect.facebook.net/en_US/fbevents.js');

fbq('init', '123456789123');
fbq('track', 'PageView');

I know Facebook and Chango are two tag types that fall in this category.

Simple Pixel

The easiest of pixels are those that just require the loading of a tiny invisible image. For instance, let’s say I got the following Yahoo dot code:

<img src="https://sp.analytics.yahoo.com/spp.pl?a=123456789&.yp=98765&js=no" height="0" >

If I want to load an image like this asynchronously, I could paste it in, unchanged, as a non-sequential HTML third party tag. As mentioned earlier, this would create an iframe that loads on the side of the page, so as to not slow down page performance.

I could also add it as a non-sequential javascript third party tag using document.body.appendChild to append it to the body, whether it has finished loading or not. This also makes it so you can add these pixels in event-based rules on SPAs or post-page-load user actions.

var dcIMG = document.createElement('img');
dcIMG.setAttribute('src', 'https://sp.analytics.yahoo.com/spp.pl?a=123456789&.yp=98765&js=no');
dcIMG.setAttribute('height','1');
dcIMG.setAttribute('width','1');
dcIMG.setAttribute('border','0');
dcIMG.setAttribute('style','display:none');
document.body.appendChild(dcIMG);

To my knowledge, Yahoo Dot, Bing, Vibrant/Intellitxt, Gumgum are examples of simple pixel code vendors.

Pixel with query params

Some vendors have simple pixels, with query parameters in the src url that helps tell the vendor what they need to know. (Coincidentally, this approach is the approach used by Adobe Analytics.) Let’s say I got this code from Doubleclick:

<!--<script type="text/javascript">
var axel = Math.random() + "";
var a = axel * 10000000000000;
document.write('<iframe src="//0.fls.doubleclick.net/activityi;src=123456789;type=clientsale;qty=1;cost=[Revenue];ord=[OrderID]?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
</script>

<noscript>
<iframe src="//0.fls.doubleclick.net/activityi;src=123456789;type=clientsale;qty=1;cost=[Revenue];ord=[OrderID]?" width="1" height="1" frameborder="0" style="display:none"></iframe>
</noscript>
<!-- End of DoubleClick Floodlight Tag: Please do not remove -->

I could add this to my site like this, using data elements in place of [Revenue] and [OrderID]:

var axel = Math.random() + "";
var a = axel * 10000000000000;

var dcIMG = document.createElement('iframe');

dcIMG.setAttribute('src', "//0.fls.doubleclick.net/activityi;src=123456789;type=clientsale;qty=1;cost="+ _satellite.getVar('purchase: revenue') +";ord="+ _satellite.getVar('purchase: order id') +"?");


dcIMG.setAttribute('height','1');
dcIMG.setAttribute('width','1');
dcIMG.setAttribute('Border','0');
dcIMG.setAttribute('style','display:none');
document.body.appendChild(dcIMG);

Pixels with Script tags

Many vendors require you to add their javascript file to your site, as well as set some variables.

For instance, I might get this code from twitter:

<!-- Twitter single-event website tag code -->

<script src="//platform.twitter.com/oct.js" type="text/javascript"></script>

<script type="text/javascript">twttr.conversion.trackPid('123456', { tw_sale_amount: 0, tw_order_quantity: 0 });</script>

<noscript>

<img height="1" width="1" style="display:none;" alt="" src="https://analytics.twitter.com/i/adsct?txn_id=l5jl4&p_id=Twitter&tw_sale_amount=0&tw_order_quantity=0" />

<img height="1" width="1" style="display:none;" alt="" src="//t.co/i/adsct?txn_id=l5jl4&p_id=Twitter&tw_sale_amount=0&tw_order_quantity=0" />

</noscript>

<!-- End Twitter single-event website tag code -->

So there is a script that needs to run, then script that needs to fire afterwards. We can remove the noscript portions, but we still need to figure out a way to get the .js script to run before I fire twitter.conversion. There aren’t a lot of options for running a .js file after a page has loaded- if you have jQuery, you can use $.ajax, but if you don’t have jQuery you can use the below to append the .js file, make sure it has completed, then run twttr.conversion:

var dcJS = document.createElement('SCRIPT');
var done = false;

dcJS.setAttribute('src', '//platform.twitter.com/oct.js');
dcJS.setAttribute('type','text/javascript');

document.body.appendChild(dcJS);
dcJS.onload = dcJS.onreadystatechange = function () {
     if(!done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete")) {
          done = true;
          callback();
 
           // Handle memory leak in IE
           dcJS.onload = dcJS.onreadystatechange = null;
           document.body.removeChild(dcJS);
     }
 };
 function callback(){
      if(done){
           twttr.conversion.trackPid(pid,{
                tw_sale_amount:_satellite.getVar('purchase: total revenue'), 
                tw_order_quantity:_satellite.getVar('purchase: total units') 
           }) 
      }
 }

Google Adwords/Remarketing, Twitter, Linkedin, and Eloqua can all fit this general idea.

5. Validate the tag

There are many tools on the internet for validating tags are working. Some vendors, like Google, may have their own tool, but most tools can be validated either within a Developer Console or by using tool-agnostic tools like Ghostery or the chrome Observepoint plugin. Most methods require opening a developer console. An easy way to do this in most browsers is to right-click anywhere on the page and select the “Inspect” option. For instance, in Chrome:

chromeConsole

First, check there are no errors in the console. Then, to validate a specific tag:

Using the Observepoint plugin: Within the developer console, go to the “Observepoint” tab:

observepoint

Click the “Recording” button, then refresh the page. Observepoint should show every tracking technology running on the page, including the one you are validating.

Using the built-in tools in your browser: Open the network tab, then refresh the page. Often you can search for the name of the tag- for instance, here I’m searching for “twitter”, and it shows me that data was sent to twitter:

netTab

Other vendors use slightly more disguised names. Check with the vendor if you need more details on how to validate.