Category Archives: DTM

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.

How do I use DTM for a Single Page App?

The question of how to use DTM on Single Page Apps (SPAs) is a VERY hot item right now. By Single Page App, I’m referring to a full user flow contained on a single web page, so as to provide the user a more seamless experience. Often, these pages act like typical web pages, but they don’t always change URLs or load new resources. Many common web development technologies, such as Angular.js, Ember.js, and AJAX use SPA principles.

Unfortunately, there isn’t a single great answer for how to deploy DTM- it depends on many things. I’ll work through some of the options and the limitations to be aware of.

Suppressing Page View Beacons

Whatever method you take for tracking page views in a SPA, keep in mind most SPAs do have one true “page view” when the DOM first loads. If you are going strictly with the DCR or EBR route, you may need to suppress the initial page view beacon the Analytics tool will want to set by default. Otherwise, in the example below where the developers are firing a direct call rule on all page views, you’d get TWO beacons on the first page and 1 on all subsequent pages.

Picture1

Data Layer Considerations

You’ll need to make sure that whatever the sources of your Data Elements are (CSS selector, javascript objects, cookies…) have the correct values BEFORE your rule is triggered. I have an example site showing one way you might do this for a data layer (though you’ll need to look in the source code), but ultimately it’s going to depend on your site.

Variable Persistence

One last consideration is that once your Analytics object exists (as in, the “s” in “s.pageName”), variables set on it will continue to exist unless specifically overwritten. In most cases, you’d overwrite s.pageName with a new value so it isn’t a problem, but something like s.eVar5 may be set on the first beacon in your SPA, and not desired on subsequent beacons. You can use s.clearVars() to “refresh” your “s” object, but you have to make sure it fires at the right time- for example, after the beacon on Page A, but before DTM starts mapping Data Elements to variables for the beacon on Page B. How you do this will depend on the overall deployment method you choose.

Deployment Methods

1) Direct Call Rules

Perhaps the most straight-forward approach is to have developers fire a Direct Call Rule, like _satellite.track(“page view”) on every thing YOU consider a page view, whether it’s a fresh new DOM or not.

Advantages: Disadvantages: 
  • You have ultimate control over when a page view in considered a page view.
  • If you need to clear out variables between beacons (for instance, you set s.eVar5 in the first beacon in the SPA, and don’t want it in the second beacon), Direct Call Rules don’t provide a great place to use something like s.clearsVars(). There are some potential work-arounds, but none are ideal.
  • Developers need to add more DTM-specific code (satellite.track) to your pages.
  • Direct Call Rules don’t allow for extra conditions (like “fire THIS logic on pageA, and THAT logic on pageB”) in the interface.
  • Direct Call Rules don’t “stack”- if multiple rules have conditions that are met, multiple rules will fire.

2) pushState or hashChange

Many SPA frameworks, like Angular, use a certain flag to let the browser know the user is viewing a new “page”.

pushState

DTM can listen for this flag in an Event Based Rule using a pushState or hashChange condition.

ADVANTAGES: DISADVANTAGES: 
  • No additional code is needed- most SPA frameworks are already firing something DTM can listen to
  • It’s an Event Based Rule, which allows you to fire clearVars(), and set extra conditions
  • Because you are listening for an event set by the framework, you have less control over timing. Updating a data layer BEFORE the “pushState” event is detected would be critical.
  • Event Based Rules don’t “stack”- if multiple rules have conditions that are met, multiple rules will fire.

3) Custom Event EBR

Another option, which feels a bit like a blend of the first two options, is to use a Custom Event-based Event Based Rule (and no, that’s not a typo- it’s an EBR based on the JavaScript Concept of a Custom Event). It’s possible Developers are already using this Custom Event concept for their own code and purposes, and DTM can just listen for it… or you can have developers set one specific to our DTM needs by using something like my digitalData.userAction hack.

ADVANTAGES: DISADVANTAGES: 
  • You have a little more control over timing
  • It’s an Event Based Rule, which allows you to fire clearVars(), and set extra conditions
  • May require more developer work- similar level of effort as DCRs
  • Event Based Rules don’t “stack”- if multiple rules have conditions that are met, multiple rules will fire.

 4) (NEW OPTION!) “dataelementchanged” Event Based Rule

Just in the last few weeks, a new option emerged as part of the AEM Context Hub integration. This allows DTM to listen for changes to certain data elements- for instance, you could have a rule fire whenever the “pageName” has changed. My friends at 33 sticks have a great blog post about this already for more info.

ADVANTAGES: DISADVANTAGES: 
  • You have a little more control over timing
  • It’s an Event Based Rule, which allows you to fire clearVars(), and set extra conditions
  • Requires careful consideration of when the data layer changes/loads
  • Event Based Rules don’t “stack”- if multiple rules have conditions that are met, multiple rules will fire.

Setting up an Event-based Rule that be fired directly like a Direct Call Rule

Update:
As proud as I am of this solution/workaround, it may be far less needed now that you can use the dataelementchanged  condition to fire an Event Based Rule. Instead of using custom events, you can just have DTM listen for when your pageName Data Element has changed. 

The current limitations

If developers want to fire a DTM rule directly from their code (say, they want to make sure a beacon fires only after their data layer is ready), typically they would fire a Direct Call Rule, with its very specific syntax: _satellite.track(“rule string here”). There are, however, some limitations to this method.

Direct Call Rules:

  • Don’t allow for multiple conditions (you can’t say “if _satellite.track(“cart add”) is fired AND the current page has “/products” in the URL“)
  • Don’t allow for multiple arguments (you can’t pass _satellite.track(“cart add”,”sku1″) to attach the added SKU to the rule)
  • Don’t allow for firing s.clearVars() before your rule sets up your analytics variables (to clear out variables from previous beacons on the same DOM).
  • Require very specific syntax- they MUST be “_satellite.track()”

And unfortunately, both Direct Call Rules and Event-based rules don’t “stack”- if a certain condition triggers multiple similar rules, each rule will fire its own beacon. This is different from Page Load Rules, where if multiple rules have conditions being met by the current page, they all wrap nicely into a single page view beacon.

An alternative

To get around some (but maybe not all) of these limitations, I’ve been playing with another possible option, where we use the Custom Event conditions of an Event Based Rule to accomplish nearly the same thing. After getting it set up, I can fire something like this:

digitalData.userAction("cart add","sku1")

…to fire an Event-Based Rule in place of a Direct Call Rule. There are a few things I need to do in DTM to make this digitalData.userAction work.

Set Up the Logic

First, I have to set up the logic in a Page Load Rule- set to fire on DOMReady (no need for it to be sooner)- that will merely hold the following as a Sequential Javascript Third Party Tag:

//make sure digitalData is defined to prevent errors
if(typeof digitalData=="undefined"){
  digitalData={}
}

//create fake DOM item to bind the event to
var fakeDiv = document.createElement('div');
fakeDiv.setAttribute('id', "dtmHolder");
fakeDiv.setAttribute('height','1');
fakeDiv.setAttribute('width','1');
fakeDiv.setAttribute('style','display:none');
document.body.appendChild(fakeDiv);

//define custom event
digitalData.userAction=function(n,details){

 document.getElementById("dtmHolder").addEventListener("dtmEvent", function(e) {
    console.info("Event is: ", e);
  })

  // First create the event
  var dtmEvent = new CustomEvent(n, {
    detail:""
  });

  jQuery("#dtmHolder").attr("detail",details)
  
  // Trigger it!
  document.getElementById("dtmHolder").dispatchEvent(dtmEvent); 
}

(Update: note that this code should not run before the DOM is created- it will create an error if you try to run it at page top because you are trying to append something to a body that doesn’t exist yet).
Now, whenever a developer fires digitalData.userAction(“string here), you can listen for that string as the Triggered Event Type in a Custom Event Event Based Rule. Obviously, you can alter the above code if you want a function named something other than digitalData.userAction.

Set Up an Event Based Rule

The rule will need to be bound to the CSs selector of the tiny fake div (“#dtmHolder”) we created for the custom event to bind to:

2016-04-20_12-38-12

You can create as many of these rules as you want, for whatever different strings you pass into digitalData.userAction()where the “triggered event type” reflects that string.

Pass Additional Info

If you want to pass a second argument ( e.g. digitalData.userAction(“cart add”,”sku1″)) I currently have that second argument  passing as a new attribute (“detail”) on the tiny invisible div, so you can access it off the “this” object directly in the rule:2016-04-20_12-41-52

You can give this a try at my ugly test site– open a developer console, turn on DTM debugging, and fire either digitalData.userAction(“cartAdd”,”sku123″) or digitalData.userAction(“pageView”) to see two example rules at work.

Run ClearVars

This opens the ability to run s.clearVars on s.t() beacons in cases where multiple beacons may be firing on a single DOM. (As a reminder, if you’re using the old DCR route, there are some hack-ish options for doing this- we call it daisy-chaining).

In an Event Based Rule, there IS a code block that runs before the Analytics tool, giving you a perfect opportunity to make sure you are starting with a ‘clean slate’ of variables: the Conditions Custom Code block. Just create a new Rule Condition with “custom” criteria, then put “s.clearVars()” in the code block, followed by “return true” (so that DTM doesn’t think some condition didn’t pass):

2016-04-20_12-52-49

You can also apply additional conditions, like “only fire this “cart add” rule on certain pages”, by adding more criteria under Rule Conditions.

Conclusion

I’m very open to suggestions and feedback on this- maybe we can crowdsource a better way, but for now, this seems to be a reasonable alternative to Direct Call Rules. Let me know what you think!

Referencing “this” in Event-Based Rules

Not many people know you can pull information out about the element that an Event-Based Rule fires on, without any custom code. Let’s say I want to fire a rule on a link that looks like this, and I want to capture the domain of the link that was clicked in eVar3:

<div partner="adobe">
     <a href="http://www.adobe.com" class="partnerExit" alt="go to our partner Adobe" target="_blank">This is an example link.</a>
</div>

I would set my rule up to correctly fire on that link (with something like “a.partnerExit”), then for eVar3 I would put %this.hostname%, where “this” refers to “this thing that the rule fired on”.

I don’t have to have to do any custom code, or have a data element set up (in fact, data elements are NOT particularly useful at pulling out information specific to the element that fired an event-based rule.)

Putting this in the interface…

Would let me access…

Which would yield this…

%this.hostname% The domain of the link that was clicked www.adobe.com
%this.href% The full URL of the link that was clicked http://www.adobe.com/
%this.src% The source of the element that was clicked (works for images, not links) (Not applicable here.)
%this.alt% The “alt” value of the element that was clicked go to our partner Adobe.
%this.@text% The internal text of the element that was clicked This is an example link.
%this.@cleanText% The internal text of the element that was clicked, trimmed to remove extra white space This is an example link.
%this.className% The class of the element that was clicked (less handy in reports, but very handy for DTM troubleshooting) partnerLink

For more advanced “DOM-scraping” you may need to take to the custom code. I find jQuery often simplifies things greatly for this. For instance, in the above example, if I wanted to get the ID not of the anchor tag, but of the <div> that HOLDS the anchor tag, I could do this in the custom code:

Note that I remembered to also add it into s.linkTrackVars, since this is an s.tl beacon (DTM automatically creates s.linkTrackVars for any variables you configure directly in the interface, but can’t know which variables you are adding to the custom code section, so you must be sure to add them to linkTrackVars or linkTrackEvents yourself, or the s.tl() beacon will ignore those variables).

How to get a global “s” object in DTM

At this point in time, by default, DTM creates your analytics object (usually an “s”, as in “s.pageName”) with a local scope. This means it should be able to be referenced from any custom code blocks within DTM that are tied to your analytics tool. However, it would NOT be accessible from code on the page (or a developer console) or even non-analytics code blocks in DTM (like Third Party Tags). This can cause some pretty big problems if you aren’t aware.

sUndefined

 

 

 

To get around this, you need to define your own s object within your library. This does mean you can’t let DTM manage your library, but the change you need to make is pretty minor. You need a “Custom” configuration, and you’ll need to “Set report suites using custom code below” (since you’re essentially going to be overwriting the “s” object that DTM created, where it set your report suites for you.

configureScode

 

 

 

 

 

 

When you open the editor, add this code to the top:

s = new AppMeasurement();
if(_satellite.settings.isStaging==true)
{s.account="myDevSuite"}else{s.account="myProdSuite"}

Make sure to replace the “myDevSuite” and “myProdSuite” with the correct report suites- these should match what you have in the interface. This uses _satellite.settings.isStaging to detect the current library and set the appropriate s_code.

 

With that in place, you should be able to access the “s” object from anywhere in DTM or on your page.

UPDATE: Because of a current quirk in DTM where it looks for the H code version of your s.account, I recommend also setting this line, below the ones above:

var s_account=s.account

This should prevent any report suite confusion on s.tl beacons from Direct Call Rules and Event Based Rules.

Setting the Products String in DTM

Enough people have asked for an example of a products string that I decided to post my example page on my server.

On the example page, you can see:

  • How to build a W3C-standard data layer object for a cart with multiple items
  • How to create a simple s.products string
  • How to create more elaborate s.products strings, including merchandising eVars.
  • What the final beacon looks like.

I hope someone out there finds it helpful!

Processing Rules vs Satellite: do you want a band-aid or a doctor?

Cross-post: I originally published this on SearchDiscovery’s blog in April 2013.

There is still one big topic from this year’s Adobe Summit standing out in my mind. I attended a few great sessions that discussed Processing Rules, and I had a hard time not interrupting when I heard attendees ask: “When should I use Processing Rules instead of a Tag Management system? Clearly, a good Tag Management tool can do practically everything Processing Rules can?” Coincidentally, someone asked a very good question on my previous post(the first in a series on moving away from using plugins), wondering how using Satellite to set a ?cid tracking parameter was different from using a Processing Rule within the SiteCatalyst admin settings. Obviously, some clarification is in order.

Do you want to spend your efforts treating the symptoms of a limited implementation, or do you want to heal the disease?

Processing rules, while an awesome tool, cannot replace a good TMS: they have a few functions in common but the methods, intention and potential are so very different. When people wonder what the difference is, it makes me wonder if sometimes we’re missing the forest because we’re too busy focusing on the trees: the little things that a processing rule or tag management system can both fix, and the day-to-day headaches that plague those responsible for maintaining a SiteCatalyst implementation. But when you step back and look at the bigger picture you realize you’ve been looking at the little issues so much that you never were able to push your implementation to the next stage- a stage that doesn’t require as much maintenance, giving you time to actually use the data you’ve worked so hard to get.

This isn’t to say you don’t need to fix the little things- most certainly you do, and both Processing Rules and Tag Management Systems have some things in common to help you do so. But never forget the bigger picture.

Treating the Symptoms

For those not very familiar with Processing Rules, they are a set of conditions and corresponding actions that are applied in between data collection and VISTA rules/data processing. For example, you can use a Processing Rule if you want to copy an eVar to a prop without changing your code, set an event whenever a specific eVar has a specific value, or assign a context variable to a variable. Processing rules are free for all Adobe Customers,  but do require a certification before they can be set up.*
*

processing rules example

The Advantages

What can a processing rule offer that a Tag Management System can not? Here are some ideas we came up with:

  1. Most obviously, they are included for free in your Adobe product. They are already accessible, waiting to be used without any big changes to your overall approach to implementation. (Of course, some might argue that big changes are* needed* for most organizations out there.) You don’t need to overhaul or fix your current implementation in order to use them.
  2. Processing rules require zero code knowledge: There is no need to touch JavaScript or Regular Expressions. Many Tag Management Systems will claim this “code-less implementation” as well, but we all know that unless you have a simple, well-constructed website and the most basic of reporting requirements, even with a great TMS some code work is necessary. Of course, some Tag Management Systems are less code-heavy than others, for example, Satellite was designed to need as little code as possible without losing any of the power and flexibility that a little bit of code can give you.
  3. Processing rules provide control in places where there is no access to a tag management tool, such as third-party pages where you can’t change your code to put a Tag Management snippet on.
  4. Processing rules can be enabled without a test cycle, completely independent of IT or QA teams. This could be both a good and a bad thing (a little testing is a good thing before touching live data), but there is no need to prove there are no adverse effects on the page to a nervous IT team, and the changes can be immediate.
  5. *Processing rules are set at the report-suite level. *In some cases, like if you are multi-suite tagged, it can be useful to have a way to change one data set without changing another.

I’m thrilled that this relatively new piece of SiteCatalyst functionality exists. It’s already been used to solve previously show-stopping problems, to clean up implementations, and to slowly move the whole industry to a not-page-code-dependent place—all good things. They are great for what they are intended for, but they are not a magical pill to heal all that ails your implementation.

How Satellite and Processing Rules differ

  1. Satellite can work with your cookies, DOM, meta tags, JavaScript objects, custom code, or data elements from previous pages.
    *A processing rule can only work with the data sent by your code, such as context data or existing SiteCatalyst variables. It can’t pull data out of your cookies, DOM, or meta tags. While it may be easier to tell your developer to set *s.contextData[‘section’]to “products” than explain what a prop is and which prop is used for what, your developer must still  know what must be captured, where to get the values for the variable, and be consistent in HOW it is set across the site. A tag management system allows you to access elements in your page, using your existing code. For instance, Satellite could “grab the value of this form field and put it into eVar40″ or “on the search results page, grab the search term from out of the header 1 tag in the content”.
  2. *Satellite requires no certification, has a support team, and you can focus your learning on the things you need.*
    **To enable processing rules, you must be certified. The test is free but asks a lot of questions that require a deep knowledge of not just processing rules, but of SiteCatalyst as a whole. I’ve seen clients farm out their processing rules work because it is simpler than training someone to pass the test, or because they don’t have enough confidence in their ability to use the tool and don’t want to mess with real, live data. Of course, this limitation could be a problem even with a TMS: there is a certain amount of knowledge and confidence you must have when making changes to live data, which leads to the next point.
  3. *Satellite has flexible, fast testing capabilities.*
    **Processing rules can be difficult to test before letting them affect live data. You can’t see them being set on your pages, with the debugger or Charles, for instance, and it can take a day or two to be sure they are working the way intended. You also can’t copy just one rule from one Report Suite to another, which can add another layer of difficulty to setup and testing.
  4. *Satellite can scale for the most complex enterprise needs.*
    **Each report suite is limited to only 50 processing rule sets. I know that sounds like it should be more more than sufficient, but I’ve already seen 2 or 3 clients hit that mark- it’s easy to do since they currently don’t allow nested conditions (as in “if … then… else…”) . Also, if an organization is using many context variables (which the newest AppMeasurement libraries do), this limit can become even more problematic.
  5. *Since Satellite code lives client-side, it can work with plugins and other code solutions you already have. *
    Depending on other reporting requirements, you may still have plugins that require certain variables like s.campaign to be set client-side, so that it can be used in script on the page- for instance, for the cross-visit-participation plugin. Many of these plugins could be worked around with a good TMS, but not with processing rules alone.
  6. *Satellite can access any SiteCatalyst variable- including RSIDs.*
    **Processing rules can’t access/change certain variables or settings, such as the report suite, hit type (page view vs. link), link type (custom, download or exit link), or products string.
  7. *Satellite leaves your implementation visible to existing free tools like Charles and firebug, and Satellite has user roles and workflow so you can manage who has visibility and control of your rules.
    *
    Visibility into processing rules is restricted to the Admin Console in SiteCatalyst. SiteCatalyst users must have admin access to see how they are set, and must know specifically the one report suite where they might be set, since you can’t view how they are set across multiple report suites like you can with your custom variables. This may seem like it isn’t a big deal, but it is definitely a pet peeve of mine to not be able to see how variables are being set, for instance while QAing an implementation.
  8. Satellite allows for for regular expressions, giving much greater flexibility. You don’t have to use it, but it’s there if you want it.
    *
    Processing rules don’t currently allow for Regular Expressions. I know I listed this as a perk (“no coding skills needed”), but it can also be very limiting. It does have the standard SiteCatalyst options in the conditions (equals, contains, starts with, is set*…) but the actions do not allow you to parse out or match values from a string. For instance, (and this is a real life recent use case), I couldn’t set up a condition to only capture the first 5 digits of the value of a query string parameter.
  9. Satellite can totally change the way your organization approaches digital measurement.

In truth, listing the things that processing rules lack really misses the point: Processing Rules are a tool to help Band-Aid (or in some cases expand) existing implementations. And they’re good for that: I’ll freely admit I have used them, and been grateful for them as a Band-Aid. But even when used with context variables to create a clean new implementation, even with many of the above limitations removed, they are *still meant to be just a mode of deployment. *

Healing What Ails You

We need to get the industry to stop viewing Tag Management as just another “mode of deployment”. As Evan rightfully put in his post a while back, Tag Management shouldn’t resemble another ticketing system. Satellite was built so that it doesn’t merely fill in the gaps of your SiteCatalyst Deployment Guide. It helps you iteratively rewrite it, from the Business Requirements on down. So while yes, many of my tactical blog posts will be about “treating symptoms”, don’t think for a moment that that is all there is to Satellite. We need to change the game, not just make it easier to play the current game. The business stake holder shouldn’t have to find someone certified in processing rules to tell them what they can and can’t track. Data collection shouldn’t be so far removed from your website that the user experience doesn’t even factor into the collection process.

So if you find yourself asking “how is this different/better than processing rules”, please reach out and let us show you that both can be good: while they do have a few tasks in common, processing rules are still a method of implementation; Satellite addresses a much bigger picture. It not only makes the day-to-day implementation easier, it can change the way you view digital measurement: the data you can bring in, the questions you can ask, and the actions you can take.

(A big thanks to Bret Gundersen and the folks at Adobe for their insight into processing rules for this post, and for the work they’ve done on that tool.)

*More information on how to set processing rules can be found at *Kevin Rogers’ blog or the Processing Rules section of the Adobe Marketing Cloud Reference site.*

SiteCatalyst Implementation Series: Breaking up with SiteCatalyst plugins

Cross-post: I originally published this on SearchDiscovery’s blog in February 2013.

We’ve all had a love/hate relationship with our SiteCatalyst plugins. I mean, where would we be today without good ol’ s.getQueryParam or s.getTimeParting? And when you have a new tracking parameter from your marketers, who doesn’t love to get your developers and implementation consultants to change and test those fateful lines in the doplugins section? But it’s time to move on. Technology has finally caught up to our needs. Plugins you previously couldn’t have lived without are now obsolete, since their functionality is built right into the Satellite interface.

I’ll admit, when Rudi Shumpert posted about how to get a SiteCatalyst Base Code (scode) into Satellite before I started working here, I thought “well, it will be nice to be able to manage/make changes to the scode right within the satellite interface, but Rudi left off a pretty critical piece- plugins! That’s where all the hard work is, anyways.” That plain little s_code you get from the admin console doesn’t include any plugins- yet somehow pretty much every scode on the web includes lines and lines of plugin code. You can’t live without them! Or at least, you couldn’t in the past. But Rudi and Satellite were already a few steps ahead of me.

Where did all those s_codes get their plugin code? Some can be found in the SiteCatalyst knowledge base documentation, some can be found smattered across the web on various blogs (I can’t tell you how often I’ve referred clients toKevin Rogers and Jason Thompson‘s blogs). Either way, you need someone familiar with the plugins, their use-cases, and their gotchas, to implement them for you: the Implementation Consultants. As someone who has made a living for 6 years as an scode jockey, I can tell you that while there is always plenty of s_code work to keep an IC busy, we’d much rather focus our efforts on streamlining processes, create better governance and standards, and helping bring in data that  can really change the way an organization does digital business.

Now that I’ve had more of a chance to work with Satellite, I see Rudi wasn’t wrong to omit plugins in his post: he just knows that with Satellite, you may simply just not need them! Take getQueryParam for example.

Query Param Tracking – The Old Way

In the past, if I used a query string parameter, such as “cid”, “cmpid”, or “source”, in my marketing URLs to track campaigns, I’d need to include this in my scode in the sdoPlugins function:

s.campaign=s.getQueryParam('cid');

Then in my plugins section, I’d need to include the whole getQueryParam plugin (hopefully the most recent version, which is currently 2.3).

/* * Plugin: getQueryParam 2.3 */ s.getQueryParam=new Function("p","d","u","" +"var s=this,v='',i,t;d=d?d:'';u=u?u:(s.pageURL?s.pageURL:s.wd.locati" +"on);if(u'f')u=s.gtfs().location;while(p){i=p.indexOf(',');i=i<0?p" +".length:i;t=s.pgpv(p.substring(0,i),u+'');if(t){t=t.indexOf('#')>-" +"1?t.substring(0,t.indexOf('#')):t;}if(t)v+=v?d+t:t;p=p.substring(i=" +"=p.length?i:i+1)}return v"); s.pgpv=new Function("k","u","" +"var s=this,v='',i=u.indexOf('?'),q;if(k&&i>-1){q=u.substring(i+1);v" +"=s.pt(q,'&','pgvf',k)}return v"); s.pgvf=new Function("t","k","" +"if(t){var s=this,i=t.indexOf('='),p=i<0?t:t.substring(0,i),v=i<0?'T" +"rue':t.substring(i+1);if(p.toLowerCase()k.toLowerCase())return s." +"epa(v)}return ''");

Now you’d wait for developers to test it, and/or for the next code release cycle. Not exactly the most clear-cut solution for something so simple, is it? In truth, this is probably the easiest, most simple plugin you can implement in your s_code. And if you wanted to keep it in your s_code, you still could, and manage it within Satellite to keep it easy to manage and control.

Query Param Tracking -The New Way

Now, you can accomplish the exact same purpose with a few keystrokes and a mouse click. In either your page rules (to apply to only a subset of pages) or your overall tool settings (to apply site-wide), you’ll find the campaign variable :

set up campaign tracking in one click

Done! Yep, that’s it.

Additional Uses

If you need to capture different query string parameters into different variables – for example, an internal promotion into ?icid – this is done with one additional step: the creation of a simple data element (under “rules” then “data elements”). Give it a friendly name for the satellite interface, select “URL Parameter” under type, enter the parameter, and save.

Creating a data element from a query string parameter

All that’s left to be done is to call that data element in the eVar itself. This can be done site wide (in your tool settings) or for a specific page or subset of pages- either way, the set up is the same and very simple. I set the eVar number, type “%” to let Satellite know I am calling a data element, choose my already-created element from the list, and hit save:

Adding the data element to an eVar.

I save my rule or my settings, test it, and publish it- a process that could be completed in as few as 5 minutes. Done. No code touched. The s_code file is still that basic, plain s_code straight from the admin console.

Conclusion and Next Steps

Obviously this is a very simple (if very common) use case. I implemented both campaign and internal promotions on my own site in under 15 minutes. I’ll be following this post by looking at other plugins that Satellite can free you from, including the linkhandler plugins, getPreviousPageName, getAndPersistValue, appendToList, Form Analysis, and forceLowercase plugins.

Are you ready to move on? Which plugins are you ready to leave behind?