The Rule Sandwich: now for the webSDK!

(Note: this was originally published March 2025 on the 33 sticks blog.)

I’ve written previously about what I’ve found to be the most scaleable method of implementing analytics in Adobe Launch*, but that was for the old Analytics/appMeasurement way of doing things. If you’re using the webSDK, the Rule Sandwich is still an option, though it works slightly differently (and is a little less intuitive, IMO).

Before I tell you how, I highly recommend reading that previous Rule Sandwich post, but if not, at a high level, the idea behind the “rule sandwich” is to have:

1. one rule that fires everywhere, that sets all your global variables- things that follow the same logic everywhere, and belong on every (applicable) event, such as login state, site section, marketing campaign…

2. a set of rules specific to particular user actions (a product details page view, a form submission, etc) where you set variables that should only be set with that user action

3. potentially a third rule to fire the event/beacon off to Adobe.

The goal is to reduce redundancy and create something that scales. If page name is ALWAYS going to come from the same place in the data layer, there is no reason to configure that over and over. If I need to make an update to one variable, I don’t want to do it in a bunch of different rules.

The “Standard” webSDK Implementation: map your XDM Object

The “default” way (and for a long time, the only way) to setup your webSDK payload was to have a single “XDM Object” data element that mapped everything. Adobe’s documentation walks through how to do this. There is one big problem, though: some XDM fields (like anything you’d base a metric on) should only be set in certain situations- for example, I only want my Internal Search Input metric to increment “1” on the Internal Search Results page. If I had a single Data Element that handled all of my XDM set up, how do I tell it to only set _experience.analytics.event1to100.event5.value to “1” when the user is on a Search Results page? You could:

  1. Have a data element for every metric, so you could use script to dynamically fill in that XDM field. If I have 50 events, that means I might have 50 data elements that each look something like this (or possibly more complicated depending on your conditions) :
if(_satellite.getVar("DDT: page type")=="search results"){
     return 1
}

…and then in your XDM Object Data Element, you’d do something like this for every one of your event fields:

  1. You could create a separate XDM object for each situation. For example, you’d have a “Search Results” rule that pulls in your “Search Results” XDM Object Data Element, which has all your global variables, plus your internal-search-specific logic. Then you’d have another “Product Details Page” rule that pulls in your “Product Details Page” XDM Object Data Element, which also has all your global variables, and so forth.
  2. You don’t set your situation-specific stuff in Launch at all, and instead use Data Prep to do something like this:

I really dislike all three of these options, though if I had to choose, I’d go with the first. Fortunately, Adobe provided another way: Update Variable.

A better option: Update Variable

To use Update Variable, you first need to create a webSDK Data Element of the type “Variable”:

This is a little unique, since it’s a Data Element that doesn’t really return something that you’d want to use, but rather just gives you abilities within your Rule Actions. The Data Element is mainly just to give you a place to specify the schema you want to follow.

Then you create rules with varying scopes, to “update the variable” as needed. At this point, you can think of it the same way you’d think of the Analytics “Set Variable” action (which can really help with migration, by the way- you can “migrate” one “Set Variables” at a time).

So, to make my rule sandwich, I’d start with a Global rule I want firing on all my events. The tricky part is covering all the different types of triggers that might fire tracking. If you’re using the ACDL extension, and not listening to any clicks or anything, then this is easy-peasy. But often it’ll end up being some combo of data layer events and clicks (and again, this is discussed in my previous Rule Sandwich post).

I’d give the trigger(s) a low “order” number (like 1, or 25… it’s all relative, just needs to be lower that my other rules). I’d create an action using the WebSDK’s “Update Variable” Action Type:

When I first open that “Update Variable” action, it will have me specify which variable I want to update, so I select the Data Element I just created. It will then create an XDM tree that matches your schema, very similar to an “XDM Object” Data Element. It even includes some helpful info, about how to tell what has been populated and how to clear out all or part of your variables as needed (which is important- we’ll get back to that later).

Since this is our global rule, I’d go through and set every field I have that should always fire, provided its data element has a value (login state, page name*, internal/external campaign tracking codes, etc).

*Note with Page Name and URL, you may not want to set that globally, particularly if this data is still bound for Adobe Analytics. Analytics bases whether or not it consider an event a “page view” (equivalent to an s.t() beacon) based on several factors, including the presence of URL or page name.

Then I’d create my situation-specific rules (my “sandwich fillings”)- things that should only fire on certain pages or certain user actions. For instance, I might have a rule specific that fires on page load, only when my page type is ”Search Results”:

Then in my “update variables” action, I would set the fields for Search Results Term, Number of Search Results, and whatever metric I want to increment to indicate the user has made a search query:

Note, when I increment a metric, I should use the number, without quotation marks- it needs to be an integer, not a string. If the data is being fed only into Analytics then it doesn’t matter as much (it seems to handle strings and integers the same), but if the data is going into CJA, this will make it so much easier to turn it into a metric.

Finally, we need to actually fire events off to Adobe’s Edge. For page views, this is where the top slice of bread comes in: a rule, with order #100, with a webSDK “Send Event” action:

For non-page-views, I may just add that event to the existing “filling” rule. This lets me specify an event type that suits that user action. OR, I may create a different “top slice of bread”, if I have many rules all tracking something similar and I tire of adding a “Send Event” action to every single one of them. (Again, all of this is detailed in the original blog post– just swap “Set Variables” for “Update Variable”, and “Send Beacon” for “Send Event”.)

The final result should be an event payload that includes fields from your global rule and any rules where you updated your variable.

Gotchas

Clear variables

In the appMeasurement/Adobe Analytics world, we had issues with variable persistence and sometimes had to clear out our variables, and the webSDK is no different. If, for example, when my page loads, I “update my variable” to set my Search Results metric to “1” and fire an event, but then the user selects a search filter and I want to update the variable and fire an event again… that Search Results metric will still be “1” in my XDM variable. My “search filter” event payload will include my search results event, as well as any event I set earlier on that page, potentially duplicating metrics.

Fortunately, the “Update Variable” allows you to clear out previously-set fields. You can do this on a field-by-field basis, but with the Rule Sandwich setup, I find it easiest to just do it on my “bottom slice” global rule- select your top-level xdm object and check “Clear Existing Value”.

(10 points if you spot the typo in the interface)

Since you’re about to re-set all your important global variables, you don’t have to worry about erasing anything you wanted to hang around. If you are concerned about clearing something important, you can focus on clearing out the fields your metrics are based on, since those tend to be the ones we don’t want hanging around. For example, I can easily clear out most of my Adobe Analytics events by just focusing on the “event1to100” objects:

Copying between properties

We came across an interesting bug when using “Update Variable” when we tried to copy the whole set up from one Launch Property to another. We copied the XDM Variable Data Element and every rule that used it. Both properties followed the same schema and used the same datastreams, so it felt like a simple lift-and-shift. In the interface, everything looked great… but nothing worked. I was just helping out (it wasn’t my client) so I didn’t have access to the Launch properties in question, so I had to resort to troubleshooting in the code… which ended up being a good thing, because only there could I have seen the “Update Variable” action doesn’t reference the XDM Variable Data Element name, but rather, some internal ID, and that internal ID seemed to be copied from the original property.

The data element itself had one ID:

But the code for the Rule with the “Update Variables” action seemed to be referencing something else altogether:

Whereas the original property (which still worked) had the same ID (the one ending “4d3d”) in both of those spots. So our new property’s Update Variables actions were seemingly trying to reference the ID of the XDM Variable Data Element from our original property.

In my testing on my own properties, I could see that it should be as simple as giving your new property’s XDM Variable Data Element a slightly different name (in my experience, it only worked if the data element had a new name, otherwise it kept trying to reference the old ID) and going through each Update Variable Action and changing its variable to your new property’s newly-renamed Data Element. In my testing, at least, I did NOT lose the mappings I had worked so hard on when I changed my variable (hooray). It is annoying to have to do this in all your Update Variable actions, but better than starting from scratch. Make sure you also update the variable reference in your “Send Event” actions.

(Since I wasn’t technically on the account in question, I didn’t submit this as a bug to client care and I don’t know if anyone else has, but someone probably should.)

What works for you?

This is a method that has worked well for me, but (as any honest agency/consultant should tell you at this point)… we’re all still figuring this webSDK/XDM/CJA stuff out as we go. Unlike appMeasurement (and H code before it), I don’t have nearly 20 years of experience to tell you all the gotchas and to be able to say which methods will withstand the test of time. I have been on alphas/betas/POCs for the webSDK since 2019, but I only have a few XDM projects where I have been able to look back a year or two later and say “that worked well” or “I wish I had done something different”.

I’m grateful for consultants from other agencies (Adswerve and Slalom, in particular) not to mention MANY individual practitioners that have helped me puzzle some of this out. We all benefit from knowledge-sharing at this point, and one of my favorite things about this industry is how much folks generally care more about learning and sharing than they care about “competition”.

I’ll update this post if I figure anything out that’s relevant, and hope folks will reach out to me if they discover something that works better, or some other gotcha folks should be aware of.

*Still not calling it “Adobe Experience Platform Data Collection Tags”

DTM-to-Launch Migration Series #3: The Migration Process

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

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

Thus far in this series, we’ve discussed your options for a DTM-to-Launch Migration, and some potential areas you can improve upon your solution as part of a migration. As you can see from my previous posts, there are a lot of possible considerations for a DTM-to-Launch migration. So what might the actual process look like to get your company on Launch instead of DTM?

Figure Out How You’ll Roll Out

Does it make sense for your org to roll Launch out all at once to all of your properties? Or would you prefer to bite off one chunk at a time? (For instance, one client is currently updating their internal search single page app, so they’re going to roll out Launch there first, as a sort of guinea pig.) Keep in mind that even if you are only rolling out Launch to 3 pages first, ANY roll out is going to have to tackle some global logic- it may be that those first three pages are the hardest because you’ll need to tackle how to handle not just the requirements for those three pages, but also global items like authentication status or global marketing tags.
If you do want to roll out all at once, you can keep using the same DTM embed code you always have so your developers don’t need to make changes to the pages, but that’s an all-or-nothing option (once you switch to Launch, Launch will “own” that embed code unless you choose to re-publish from DTM), and it only works in prod (dev/staging environments will still need the new embed codes).

Also, if you’re considering having DTM and Launch run alongside each other on the same page…. don’t even consider this an option. It won’t work. Both tools use the _satellite object and one WILL overwrite the other and/or get very confused by the presence of the other.

Validation

Keep in mind the effort to validate things- even if you are doing a “simple lift-and-shift”, you will still need to validate that Launch is doing all the things that DTM had been doing. Depending on how well-documented your current implementation is, and/or what QA efforts are currently in place, this may mean figuring out what it is that DTM is currently doing so you know whether Launch is matching it or not. This is a golden opportunity to set up some QA processes, if you haven’t already.
If you don’t have a solid process already in place, you won’t be able to test every possible beacon for every possible user, but you should can set up a testing procedure in place for critical beacons on your most typical flows. Note, none of this is specific to DTM or Launch, but is a best practice regardless and will help with the DTM-to-Launch migration.

  • Establish key user flows and document each beacon in the flow’s expected variables
  • Use a tool like Observepoint or Hub’scan to automate testing
  • For your KPIs, in Adobe Analytics set up anomaly detection and/or alerts based on reasonable thresholds (alert me if revenue dips below $___ or visits climbs above ___)

This is all much easier if you used the migration as a chance to document your solution.

Audit What You’ve Got and What You Want

Unfortunately, Adobe does not provide a great way to document all of your current rules and data elements in DTM. Fortunately, there is a tool to help: Tagtician has a free chrome extension that can create a spreadsheet with a list of all your data elements, rules (including third party tags and what is deployed in the Adobe Analytics/Google Analytics section of each rule.) I cannot overstate how incredibly helpful this has been for every DTM migration project I’ve been on.
Depending on how ambitious our migration plans are (on a scale of “lift-and-shift” to “burn it down and start fresh”), I’ve used this as a basis for a new solution design, so we know on each user action what variables are expected, where those variables are set, and where they pull their information from:

Then I take that to figure out how to deploy it through Launch (which may or may not look anything like how it was deployed in DTM): for instance, if pageName is always going to get it’s value from the same data element, I can set that in a global rule that fires on all page loads. Whereas my search variables can get their own rule, which will combine with the global rule on the search results page to create one analytics beacon with all the variables I need. Now that you can control load order and when analytics beacons fire in Launch, you may be able to really compartmentalize logic based on scope and get rid of redundancy in your implementation.

Decide On Your Publishing Flow

Launch has a new publishing flow- it’s no longer just staging vs production. You now have development (as many environments as you need), staging, and production; no changes automatically get built into a library unless you set it up to; you can use libraries to group together changes and move a group through the flow. If you only have one person in Launch at a time, and that one person tends to do most approvals and publishes, then the flow can definitely seem like “too much.” But for a lot of bigger organizations, this new flow is a game changer.
Part of moving to Launch is figuring out how this flow should apply to your organization. For example, one client came up with something similar to this:

At the start of each sprint, they create a library with that sprint name, and link it to the main dev environment. Each member of their analytics team has their own permanent library in dev, linked to alternative dev environments (which aren’t referenced by any pages and are only really interacted with through the switcher plugin- basically a sandbox for them to build in, using the switcher plugin to see the effect of their efforts in dev). As changes are completed and pass their first round of validation, they get moved into the Sprint’s library, which at the end of the sprint moves into Staging, where it is validated by the developer/UX QA team before being approved and published. (This is just an example- there is no single “right way” to use this flow, it was designed to be flexible for a reason.)
Be aware, once a library has “claimed” an environment (which is linked to an embed code), no other library can claim that environment, so if you want multiple libraries you will need multiple dev environments.
Also, you can no longer use code in a developer console to switch between environments- currently, the only way I know to switch between environments is to use the Search Discovery switcher chrome extension or to use something like Charles Proxy Map Remote.

The Migration Project Plan

A DTM-to-Launch migration can become quite the involved project. For the simplest of migrations, it still may be 4-6 weeks to migrate within the tools, do any necessary validation, and publish your changes. It may only need to be one or two main analytics/TMS folks and/or a QA person working on it.
Or, it may be a 9 month project that involves devs, QA/UAT, data architects, analysts… don’t underestimate the resource cost of the migration (though at the same time, don’t undervalue the long-term resource savings if you take the time to get it right as part of the migration and (re)build a scalable, maintainable, well-documented solution.)
For instance, below is an example of how a Launch migration could go. This example does not include any changes to the data layer, but does include a substantial attempt to re-deploy analytics rather than merely shift the existing implementation with all the same rules and data elements.

Next Steps and Resources

As you can see, even a simple lift-and-switch to Launch can be a bit involved, and folks can feel daunted by all the considerations, options, and things to be aware of. I’ve tried to be as thorough and comprehensive as possible in this series, and I hope I hit the right level of detail to give practical guidance on how to tackle a DTM-to-Launch migration. There is a great community out there for folks who need DTM/Launch support- check out the following resources:

Hopefully this series helped, but feel free to reach out if you have questions or if you’d like to engage with us to make sure you get off on the right foot as you move to Launch.

DTM-to-Launch Migration Series #2: A Golden Opportunity

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

(Cross-posted from the 33 Sticks blog)

Aside from all of the things that Launch handles better than DTM did (which I discussed a bit in my previous post in the series), a move to Launch provides an opportunity to clean up and optimize your implementation (to the point that even if you weren’t moving to Launch, you could still do this clean up within DTM). You can save yourself from headaches and regret down the line if you take the time now to define some standards, adopt some best practices, or apply some “lessons learned” from your DTM implementation.

Redo Your Property Structure

Many companies set up their DTM properties based on a certain understanding of how properties should be used, and realized a bit too late that a different set up might work better.
previous post of mine on this topic is still applicable in Launch: your properties should not be based on Report Suites or domains, but rather, on the three following questions:

  • How similar are the implementations between your sites (do they use the same data layer, for instance? Would the rules be triggered by the same conditions?)
  • How similar are the publication timelines (if you publish a change for Site A, would it also apply to Site B at that time?)
  • Will the DTM/Launch implementation be maintained/updated by the same folks? (Properties are a good way to control user access.)

Keep in mind Launch has an API for configuration, so if you have 15 properties and want to make a change to all of them at once, you now can (though that API is not yet super documented/supported, so it’s a bit of a wild west so far). In general, I’ve seen folks using Launch as an opportunity to move to fewer properties.

Define Standards and Best Practices

Now is a great time to take lessons learned from DTM and define the standards your company will follow within Launch. Some things are arbitrary- it doesn’t really matter if I name the rule “Product Details Page View” or “page: product details”, but if we are consistent from the start, it can save us a lot of head ache and cleanup down the road.

Tags With the Same Condition(s)/Scope Should Share the Same Rule

To keep your library light, and your implementation scalable and maintainable, I highly recommend basing your rules on their scope/condition, rather than the tags they contain. For instance, a single rule named “Checkout: Order Confirmation” is better than 10 different rules that fire on Order Confirmation- “Doubleclick Order Confirmation” and “Google Conversion Tags”, etc.
I’ve written previously about why this matters– it can have a surprising affect on page performance (not to mention it cane make your TMS impossible to navigate/maintain), and that still applies in Launch.

Delete redundant and unused stuff

Run an audit of your DTM property. Do you have redundant or unused Data Elements? Empty (or permanently commented-out) rules or Third Party Tags? Inactive rules or data elements that aren’t likely to ever be used again? Often folks are afraid to delete things within DTM, but this is a great chance to delete anything that isn’t still useful.

Institute a Naming Schema

This is your chance to have a nice, clean naming standard in your TMS. Consider all the following things you can name in Launch:

  • Data Elements: I try to keep to the same [category]:[details], though since Launch doesn’t show the DE type from the DE list like DTM does, I also like to include the type: “search: term: QP” (QP for Query Parameter) or “checkout: order total:DL” (DL for Data Layer). I also prefer keeping everything for Data Elements lowercase so I don’t have to worry/remember how I capitalized things.
  • Rules: In DTM I liked to do something like “[category]:[scope/condition]” (eg “Search: Results”, “Catalog: Product Details”, “Checkout: Cart View”.) In Launch, because DCRs, EBRs and PLRs now share the same interface, I like to take it a step further and include the rule type at the front: “Page: Search: Results” or “Click: Search: Filter”. If you have a lot of rules potentially firing into the same beacon, then I’d also include info about the order (eg, “Page: Global: All Pages #100” and “Page: Home #25” so you know that the #100 one would fire AFTER the #25 one on the home page.) I’ve also found it helpful to call out the rules which actually fire my analytics BEACON as opposed to rules that run higher in the order and only set variables (eg: “Page: Global: All Pages (s.t) #100”). Then within Rules, there are more naming considerations than there had been in DTM:
    • Events: Should be descriptive, and it may be worth including the load order (so “Page Top- #100” or “Direct Call: Add to Cart #50” might do the trick.)
    • Conditions/Exceptions: Conditions and Exceptions particularly should have some sort of custom naming (instead of a condition “Core – Value Comparison”, I might name it “pageName DE=’search results’”).
    • Actions: I’ve been leaving some with the default (eg, “Adobe Analytics – Set Variables”, though depending on how complicated my implementation is, I might want to change that to “Analytics- Content Identification variables”). Any Core/Code actions should have a descriptive name (“Yahoo pixel- expires 12/19/19” or similar.)

Fix Up Your Data Layer

This is perhaps a very ambitious task for most migrations, but if you’re already taking the effort to audit your DTM implementation, now might be a good time to also look at your data layer- do you have data layer objects that aren’t being used in DTM at all currently? (Be aware, of course, that data layers don’t always exist solely for a TMS’s sake- make sure no one else is using it either). Before you go creating a bunch of data elements, is there something you wish your data layer had that it currently doesn’t? Or do you wish it were structured differently? Now might be a good chance to optimize it! Especially if you are rolling Launch out to one part of your site at a time, you may be able to work with devs to break up a Data Layer rollout into reasonable chunks. You may be surprised by how many devs are on board with fixing up the data layer, particularly if your current on is messy/confusing.

Move Third Party Tags to Asynchronous JS

This is one of the biggest areas for improvement I’ve seen amongst my current and past clients- they’ve potentially been using DTM for years and haven’t always taken advantage of DTM’s ability to improve page performance by moving third-party tags to asynchronous javascript.All tag managements systems have inherent weight- you are adding a JS library to your site. If you don’t mitigate this weight by using the TMS to optimize your tags, your TMS may be having a net-negative affect on your site- a substantial one, in many cases. I’ve written previously about the approach I would recommend for third-party tags, but to emphasize the importance of this: I have seen the overall page load time improve by 15-30% by simply moving tags within DTM to async. Unless the vendor’s code affects the user experience (chat, survey or optimization tools, for instance), there is no reason for most tags to be anything other than non-sequential JS.

In Launch, you can take it a step further, and use extensions to further optimize your tags. For instance, if you use Facebook or Doubleclick, there are extensions in place that you can use to move those tags entirely out of custom code blocks. Or, if you are deploying a simple pixel tag and the vendor does not have an extension, you can use 33 Sticks’ Pixel Loader extension to easily change it from an html  tag to asynchronous javascript.

Document Everything!

Moving to Launch also provides the ability to get solid, current documentation on your solution. Aside from auditing your solution (I’ll take about that in a moment) so you know which rules are setting what or what is expected in the Data Layer on certain pages, I also recommend using this fresh start as a change to document and enforce your standards and best practices for TMS deployment. For instance, I’ve helped clients create a confluence document that anyone at thier company who might be within Launch can access, detailing:

  • Naming Strategy (see notes above)
  • Third Party Tag deployment standards (which tags are “approved” by your org for use- as in, “do not use one TMS to deploy another TMS like GTM, not unless you hate your site loading quickly”); deploying tags as asynchronous JS- see note above…)
    • I also recommend as part of the auditing/documentation process getting a list of all your third party tags, documenting who at your org “owns” that tag, and setting “expiration/renewal” dates (“Jan Smith owns this floodlight tag, deployed 8-5-18; on 9-5-18 we will contact her to see if the tag is still valid or can be deleted”).
  • Best Practices (don’t check “apply handler directly to element” without good reason, try to limit the number of Data Elements used in “Data Element Change” rule triggers, etc.)
  • Publication Flow (how is your org using libraries and environments? Who approves and who publishes? Will publishing happen with a specific cadence, like every other Wednesday? What is your QA/validation process? Do you want to implement an “all changes must be reviewed by someone other than the person who made the change” rule?)

I know this level of documentation can be daunting and seem like overkill, but your future staff/employees will thank you for it, even if it’s informal and/or a work-in-progress.

Change Your Deployment Method (Adobe-Managed vs Self-Hosted)

DTM had a few deployment options:

  • An Adobe/Akamai-hosted library (ie, your embed code starts with “//assets.adobedtm.com”)
  • An FTP self-hosted library (DTM would push changes through FTP to a location on your own servers)
  • A downloaded self-hosting option (you would manually download after changes and put onto your servers).

Now may be an opportunity to change this- if you’ve been doing the manual download option because of security concerns, now that the publishing flow in Launch is more flexible/powerful, might you be able to simplify by moving to another option?

Technically, all three of these options also exist in Launch, though the approach is slightly different. I’ve documented in a separate post how you can achieve each of the three methods in Launch- especially the download method, which may not be intuitive for users who had used the download option in DTM.

Update Your visitorID/appMeasurement Libraries

A TMS upgrade is also a good chance to update to the most recent stable Adobe libraries (for instance, as of this moment, the most current Analytics library is 2.10). Unless you are doing something very custom/weird in your libraries (or are stuck in the dark ages on H code), updating should be a relatively easy process, and offers benefits like improved page performance.

It may also make sense to examine your doPlugins function (if you are still using it): do you have functionality you can move out of doPlugins (eg, do you still really need getQueryParam when you can just use the DTM/Launch interface?) (Also, word on the street is that some folks at Adobe may be releasing an extension to handle many of the common plugins, so that may provide some extra room for enhancement.)

Update cross-Adobe Tool integrations

If you’re not yet on the VisitorID service, you really should be. Then once you are on that, now would be a good time to update your implementation for integrating analytics with other Adobe tools:

  • If you use Target, are you on at.js (and is it current)? Do you have Analytics 4 Target (A4T) set up?
  • If you use Audience Manager, have you transitioned to a server-side integration? Are you currently deploying your DIL at the bottom of your Analytics code in DTM, and might you be able to transition that to use the AAM extension?

What’s Next

By now, you should have a sense of what type of migration path you’re going to take, and what aspects of your solution you may want to change or improve upon. The next post in the series will walk you through the actual process and provide a rough framework for a project plan.

DTM-to-Launch Migration Series #1: Options and Considerations

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

(cross-posted from the 33 Sticks Blog)

Adobe’s Launch is really building momentum (they just announced the plan to sunset DTM– editing abilities end December 31st, 2019 July 1st, 2020; read-only access dies June 2020 December 31st, 2020 (dates updated to reflect Adobe’s change)), and in the past few months, it feels like almost every day, I get asked “what does a launch migration look like?”

And I’m afraid I have a very unhelpful answer: it totally depends.

We’ve had visibility into about a dozen migrations now, and each one has been a completely unique case. But I figured I can at least defend my answer of “it depends” by clarifying what it depends on, what the options are, and what considerations should you make.

WHAT YOU NEED TO KNOW

Preparing to Migrate
 Adobe DTM to Launch Migration Options
 Things to be aware when moving from DTM to Launch

Using the Migration as an Opportunity
 Redo your property structure
 Define standards within Launch
 Clean up redundant/unused items
 Best practices for Rule scope/conditions
 Institute a Naming Schema
 Fix up your data layer
 Optimize your third party tags
 Document everything
 Change your deployment method
 How to use the download option
 Update your visitorID/appMeasurement libraries
 Update cross-Adobe Tool integrations

The Migration Process
 How to roll out Launch
 Validation
 Audit what you have (and figure out what you want)
 Decide on a publishing flow that works for your org
 Create a Migration Project Plan
 Other Resources and Next Steps

Disclaimer: Info in this series is accurate as of, October 29, 2018. We will try to update it as it makes sense to do so, but things can change quickly in the world of TMSes and iterative product releases.

You’ve Got Options

As far as we see it, if you’re considering a move from Adobe DTM to Launch, you have a few options:

  1. Use the DTM-to-Launch Migration tool (SEE: Adobe’s documentation), essentially just doing a lift-and-shift of your current DTM implementation.
  2. Use the DTM-to-Launch migration tool, but do a fair amount of clean up before/after.
  3. Use a tool like Tagtician to audit what you currently have, decide what you want to carry over, and set it up “fresh” in Launch (have Launch accomplish the same thing as DTM, but perhaps accomplish it in different ways).
  4. Use this as a chance to rebuild your solution from the ground up.

Most folks we’ve talked to or worked with are looking at somewhere in that 2-3 range. In most cases, we’d strongly discourage going with option #1, that straight-up lift-and-shift. I PROMISE there is some room for review and improvement in your DTM implementation.

First, not everything in DTM will work in Launch. Our friends at Search Discovery have a great tool for detecting places within DTM that you may be using code that will no longer work (goodbye, _satellite.getQueryParam). (NOTE: this detects places in your DTM library you are using those “forbidden” functions- if you are using something like _satellite.getQueryParam in your own javascript outside of DTM, it will not detect it.)

Technically, aside from the things that that tool will flag, everything that worked in DTM should work in Launch (actually, there are a few major differences you should be aware of). BUT, many of the workarounds you may have resorted to in DTM are no longer needed, so you can definitely optimize things. There are some broader differences between DTM and Launch that open the door for some changes to your implementation that could be really valuable.

Consider the following questions:

Are you currently using DTM for Single Page Apps? (if so, you’ve almost certainly had to use some workarounds that are no longer needed)

Do you have any repeated global logic (all of your DCRs or EBRs might be setting “eVar5=%auth status%” because you didn’t have a way to get that eVar included on all beacons otherwise)

Do you use Direct Call Rules heavily?

Do you have s.clearVars running in odd places?

Are a large portion of your Analytics variables being set in custom code blocks instead of in the interface?

Do you fire any Direct Call Rules from within your DTM implementation (eg, DCRs calling other DCRs to get around timing/scope issues?)

Are you currently firing Adobe Analytics beacons from outside of the Analytics Tool (eg, are you using a third party tag box to fire s.t or s.tl because of timing issues?)

If you answered yes to any of the above questions (and perhaps even if not), then you absolutely should be considering moving to Launch ASAP, for all the reasons discussed on these other blog posts:

Differences between DTM and Launch to be Aware of

33 Sticks Logo- Orange Circle with 3|3

(cross-posted from the 33 Sticks blog)

There’s a lot of talk about how Adobe Launch is backwards-compatible- that, aside from a few _satellite methods that may not still work (that were probably not supported to begin with), anything you had in DTM should still work in Launch. But, well, not EVERYTHING in DTM is still going to work in Launch, and some things in Launch may catch you off guard. Here are some things you should be aware of:

Far fewer things happen automatically. For instance, Adobe Analytics no longer automatically fires a beacon on page load (which I view as a wonderful thing, but you still need to be aware of it). You need to set it up (and things like loading Target or firing Mboxes) in a rule.

 The following _satellite methods (among others, but these are the most common) are no longer supported (or, in some cases, may never have been supported but now simply won’t work).

  • _satellite.getQueryParam/_satellite.getQueryParamCaseInsensitive
  • _satellite.notify (this still technically works, but you should migrate to _satellite.logger)
  • _satellite.URI
  • _satellite.cleanText
  • _satellite.setCookie (which is now _satellite.cookie.set) and _satellite.readCookie (which is now _satellite.cookie.get)

 There is some interface functionality in DTM that is not yet in Launch:

  • There is no “notes” functionality currently (though I hear that is coming soon)
  • It’s not easy to do a revision comparison (diff compare) currently (though again, I hear that is in the works).

 Launch still has console debugging, but it no longer alerts you to what “SATELLITE DETECTED” (which I used a lot to troubleshooting bubbling issues)- it merely tells you what rules are firing, etc.

 Some tools like Tagtician or Disruptive Advertising’s DTM Debugger are not yet fully Launch-compatible. (Tagtician supports Launch but is working on improving how it handles it; I don’t know if the DTM Debugger has any plans to become Launch-compatible).

 The Adobe Analytics extension does not support multiple Adobe instances, nor can you have multiple Adobe Analytics extensions installed. (Multi-suite tagging is still ok).

 The Google Analytics extension does not support multiple GA instances.

 Some things have been renamed in a way that may throw you off- for instance, you can still easily have a Rule condition be based on a Data Element value- it’s just named “Value Comparison” now.

 While Launch gives you much more control over the order things happen in, be aware that while actions within a rule will START in the specified sequence, they may not COMPLETE in sequence: Action 1 will start, then Action 2 will start whether Action 1 is finished or not. This is particularly significant if the actions are just code (for instance, I had my first action try to pull information from an API, and my second action then use that info to fire a pixel… but the pixel kept firing before the API had done its thing). I hear that users may eventually get more control over this, but for now this is how it is.

 Adapters can be confusing (fortunately Jimalytics clears it up nicely on his blog). These days, Adobe automatically creates a “Managed by Adobe” adapter, and that single adapter should work for multiple environments.

None of these are necessarily a reason to not upgrade- especially since Adobe now has a plan for sunsetting DTM. But hopefully you won’t be caught unaware by any of these items. Has anything else surprised you about Launch? Let us know!

Adobe Launch’s Rule Ordering is a big deal for Single Page Apps

In November, I posted about some of the ways that Launch will make it easier to implement on Single Page Apps (SPAs), but I hinted that a few things were still lacking.
In mid-January, the Launch team announced a feature I’ve been eagerly awaiting: the ability to order your rules. With this ability, we finally have a clean and easy way to implement Adobe Analytics on a Single Page App.

The historical problem

As I mentioned in my previous post, one of the key problems we’ve seen in the past was that Event-Based Rules (EBRs) and Direct Call Rules (DCRs) can’t “stack”. Let me explain what I mean by that.

Not a single page app? Rule Stacking rocks!

For example, let’s say I have an internal search “null results” page, where the beacon that fires should include:

  • Global Variables, like “s.server should always be set to document.hostname”
  • Variables specific to the e-commerce/product side of my site with a common data layer structure (pageName should always be set to %Content ID: Page Name%)
  • Search Results variables (like my props/eVars for Search Term and Number of Search Results, and a custom event for Internal Searches)
  • Search Results when a filter is applied (like a listVar for Filter Applied and an event for User applied Search Filter)
  • Null Results Variables (another event for Null Internal Searches and a bit of logic to rewrite my Number of Search Results variable from “0” to “zero” (because searching in the reports for “0” would show me 10, 20, 30… whereas “zero” could easily show me my null results)

With a non-SPA, when a new page load loads, DTM would run through all of my page load rules and see which had conditions that were matched by the current page. It would then set the variables from those rules, then AFTER all the rules were checked and variables were set, DTM would send the beacon, happily combining variables from potentially many rules.

Would become this beacon:

If you have a Page Load Rule-based implementation, this allows you to define your rules by their scope, and can really use the power of DTM to only apply code/logic when needed.

Single Page App? Not so much.

However, if I were in a Single Page App, I’d either be using a Direct Call Rule or an Event-Based Rule to determine a new page was viewed and fire a beacon. DCRs and EBRs have a 1:1 ratio with beacons fired- if a rule’s conditions were met, it would fire a beacon. So I would need to figure out a way to have my global variables fire on every beacon, and set site-section-specific and user-action-specific variables, for every user action tracked. This would either mean having a lot of DCRs and EBRs for all the possible combos of variables (meaning a lot of repeat effort in setting rules, and repeated code weight in the DTM library), or a single massive rule with a lot of custom code to figure out which user-action-specific variables to set:

Or leaving the Adobe Analytics tool interface altogether, and doing odd things in Third Party Tag blocks. I’ve seen it done, and it makes sad pandas sad.

The Answer: Launch

Launch does two important things that solve this:

  1. Rules that set Adobe Analytics Variables do not necessarily have to fire a beacon. I can tell my rule to just set variables, to fire a beacon, or to clear variables, or any combination of those options.
  2. I can now order my rules to be sure that the rule that fires my beacon goes AFTER all the rules that set my variables.

So I set up my 5 rules, same as before. All of my rules have differing conditions, and use two similar triggers: one set to fire on Page Bottom (if the user just navigated to my site or refreshes a page, loading a fresh new DOM) and one on Data Element Changed (for Single Page App “virtual page views”, looking at when the Page Name is updated in the Data Layer).

UPDATE: I realize now that you probably wouldn’t want to combine “Page Bottom” and “Data Element Changed” this way, because odds are, it’s going to count your initial setting of the pageName data element as a change, and then double-fire on page load. Either way, it’s less than ideal to use “data element changed” as a trigger because it’s not as reliable. But since this post is already written and has images to go with it, I’ll leave it, and we can pretend that for some reason you wouldn’t be updating your pageName data element when the page initially loads. 

When I create those triggers, I can assign a number for that trigger’s Order:


One rule, my global rule, has those triggers set to fire at “50” (which is the default number, right in the middle of the range it is recommended that I use, 1-100). The rule with this trigger not only sets my global variables, it also fires my beacon then clears my variables:

Most of my other rules, I give an Order number of “25” (again, fairly arbitrary, but it gives me flexibility to have other rules fire before or after as needed). One rule, my “Internal Search: Null Results” rule is set to the Order number “30”, because I want it to come AFTER the “Internal Search: Search Results” rule, since it needs to overwrite my Number of Search Results variable from “0” (which it got from the data layer) to “Zero”.

This gives me a chance to set all the variables in my custom rules, and have my beacon and clearVars fire at the end in my global rule (the rule’s Order number is in the black circles):

I of course will need to be very careful about using my Order numbers consistently- I’m already thinking about how to fit this into existing documentation, like my SDR.

Conclusion

This doesn’t just impact Single Page Apps- even a traditional Page Load Rule implementation sometimes needs to make sure one rule fires after another, perhaps to overwrite the variables of another, or to check a variable another rule set (maybe I’m hard coding s.channel in one rule, and based on that value, want to fire another rule). I can even think of cases where this would be helpful for third party tags. This is a really powerful feature that should give a lot more control and flexibility to your tag management implementation.

Let me know if you think of new advantages, use cases, or potential “gotchas” for this feature!

Quick poll: What should I tackle next?

Each new year, I tend to dive into some new side project (this is how the Beacon Parser and the PocketSDR came about). I have quite a few things I want to tackle right now, and one main thing I’m slowly plugging away at, but in the meantime, I’m wondering what to prioritize. So, a poll:

Any other ideas (or desired improvements to existing tools)? Let me know in the comments.

Adobe DTM Launch: Improvements for Single Page Apps

For those following the new release of Adobe’s DTM, known as Launch, I have a new blog post up at the Cognetik blog, cross-posted below:

It’s finally here! Adobe released the newest version of DTM, known as “Launch”. There are already some great resources out there going over some of the new features (presumably including plenty of “Launchey Launch” puns), which includes:

  • Extensions/Integrations
  • Better Environment Controls/Publishing Flow
  • New, Streamlined Interface

But there is one thing I’ve been far more excited about than any other: Single Page App compatibility. I’ve mentioned on my personal blog some of the problems the old DTM has had with Single Page Apps:

  • Page Load Rules (PLRs) can’t fire later than DOMready
  • Event-Based Rules (EBRs) and Direct Call Rules (DCRs) can’t “stack” (unlike PLRs, there’s a 1:1 ratio between rules and analytics beacons, so you can’t have one rule set your global variables, and another set section-specific variable, and another set page-specific variables, and have them all wrap into a single beacon)
  • It can be difficult to fire s.clearVars at the right place (and impossible without some interesting workarounds)
  • Firing a “Virtual Page Load” EBR at the right time (after your data layer has updated, for instance) can be tricky.

So much of this is solved with the release of DTM Launch.

  • You can have one rule that fires EITHER on domReady OR on a trigger (Event-based or Direct Call).
  • You have a way to fire clearVars.
  • You can add conditions/exclusions to Direct Call rules

There are other changes coming that will improve things even further, but for now, these changes are pretty significant for Single Page apps.

Multiple Triggers on a Single Rule

If I have a Single Page App, I’ll want to track when the user first views a page, the same as for a “traditional” non-App page. So if I’m setting EBRs or DCRs for my “Virtual Page Views”, I’d need to account for this “Traditional Page Load” page view for the user’s initial entry to my app.
In the past, I’d either have a Page Load Rule do this (if I could be sure my Event-Based Rules wouldn’t also run when the page first loaded), or I could do all my tracking with Event-Based Rules, and I’d have to suppress that initial page view beacon. I may end up with an identical set of rules- one for when my page truly loads, and one for “Virtual Page Views”.

Now, I can do this in a single rule:

Where my “Core- Page Bottom” event fires when the page first loads (like an old Page Load Rule):

…and another “Page Name Changed” event that fires when my “page name” Data Element changes (like an old Event-Based Rule):

No more need to keep separate sets of rules for Page Load Rules and Virtual page views!

Clearing variables with s.clearVars()

Anyone who has worked on a Single Page App, or on any Adobe Analytics implementation with multiple s.t() beacons on a single DOM, has felt the pain of variables carrying over from beacon to beacon. Once an “s” variable (like s.prop1) exists on the page, it will hang around and be picked up by any subsequent page view beacon on that page.

Page 1

Page 2

Page 3

Page 4

s.pageName

Landing

Search Results

PDP > Red Wug

Product List

s.events

(blank)

event14

prodView

prodView

s.eVar1 (search term)

(blank)

Red Wug

Red Wug

Red Wug

My pageName variable is fine because I’m overwriting it on each page, but my Search Term eVar value is hanging around past my Search Results page! And on pages where I don’t write a new events string, the most recent event hangs around!

In the old DTM, I had a few options for solving this. I could do some bizarre things to daisy-chain DCRs to make sure I could get the right order of setting variables, firing beacons, then clearing variables. Or, I could use a hack in the “Custom Code” conditions of an Event-Based Rule, to ensure s.clearVars would run before I started setting beacons. Or, more recently, I could use s.registerPostTrackCallback to run the s.clearVars function after the s_code detected an s.t function was called.

Now, it’s as simple as specifying that my rule should set my variables, then send the beacon, then clear my variables:

Directly in the rule- no extra rules, no custom code, no workarounds!

Rule Conditions on ALL Rule Types (including Direct Call)

If I were using Direct Call Rules for my SPA, in the past, I’d have to account for Direct Call Rules having a 1:1 relationship with their trigger. If I had some logic I needed to fire on Search Results pages, and other logic to fire on Purchase Confirmation pages, I could have my developers fire a different “_satellite.track” function on every page:

Then in each of those rules, I’d maintain all my global variables as well as any logic specific to that beacon. This could be difficult to maintain and introduces extra work and many possible points of failure for developers.

Or, I could have my developers fire a global _satellite.track(“page view”) on every page, and in that one rule, maintain a ridiculous amount of custom code like this:

This would take me entirely out of the DTM interface, and make some very code-heavy rules (not ideal for end-user page performance, or for DTM user experience — here’s hoping your developer leaves nice script comments!)

Now, I can still have my developers set a single _satellite.track(“page view”) (or similar), and set a myriad of rules in Launch, each using that same “page view” trigger, but each with a condition so you can set different variables in different rules directly in the interface when your developers fire _satellite.track(“page view”) on your Search Results versus when they fire _satellite.track(“page view”) on your Purchase Confirmation page:

I’d love to say all my SPA woes were solved with this release, but to show I haven’t entirely drunk the Kool-aid, I will admit some of my most wished-for features (and extensions) aren’t in this first release of Launch. I know they’re coming, though- future releases of Launch will add additional features that will make implementing on a Single Page App even simpler, but for now, it still feels like Christmas came early this year.

Deploying Google Marketing Tags Asyncronously through DTM

I had posted previously about how to deploy marketing tags asynchronously through DTM, but Google Remarketing tags add an extra consideration: Google actually has a separate script to use if you want to deploy asynchronously. The idea is, you could reference the overall async script at the top of your page, then at any point later on, you would fire google_trackConversion to send your pixel. However, this is done slightly differently when you need your reference to that async script file to happen in the same code block as your pixel… you have to make sure the script has had a chance to load before you fire that trackConversion method, or you’ll get an error that “google_trackConversion is undefined”.

Below is an example of how I’ve done that in DTM.

//first, get the async google script, and make sure it has loaded
var dtmGOOGLE = document.createElement('SCRIPT');
var done = false;

dtmGOOGLE.setAttribute('src', '//www.googleadservices.com/pagead/conversion_async.js');
dtmGOOGLE.setAttribute('type','text/javascript');

document.body.appendChild(dtmGOOGLE);
dtmGOOGLE.onload = dtmGOOGLE.onreadystatechange = function () {
 if(!done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete")) {
 done = true;
 callback();

 // Handle memory leak in IE
 dtmGOOGLE.onload = dtmGOOGLE.onreadystatechange = null;
 document.body.removeChild(dtmGOOGLE);
 }
};

//then, create that pixel
function callback(){
 if(done){ 
 /* <![CDATA[ */
 window.google_trackConversion({
 google_conversion_id : 12345789,
 google_custom_params : window.google_tag_params,
 google_remarketing_only : true
 });
 //]]> 
 }
}

Why (and why not) use a Data Layer?

What’s a Data Layer?

Tag Management Systems can get data a variety of ways. For instance in DTM you can use query string parameters, meta tags, or cookie values- but in general, data for most variables comes from one of two sources:

  • To really take advantage of a tag management system like DTM, I may choose to scrape the DOM. I’m gonna call this the MacGyver approach. This uses the existing HTML and styles on a site to For instance, DTM could use CSS selectors to pull the values out of a <div> with the class of “breadcrumb”, and end up with a value like “electronics>televisions>wide-screen”. This relies on my site having a reliable CSS structure, and there being elements on the page that include the values we need for reporting.
  • If I want even more flexibility, control and predictability, I may work with developers to create a data layer. They would create a JavaScript object, such as “universal_variable.pageName”, and give it a value based on our reporting needs, like “electronics | televisions | wide-screen > product list”. This gives greater control and flexibility for reporting, but requires developers to create JavaScript objects on the pages.

Conceptually speaking, a data layer is page-specific (but tool-agnostic) metadata that describes the page and the actions a user may take on it. Practically speaking, a data layer typically consists of a JavaScript object that contains all of the values we’d want to report on for a given page or user.

Data layers are important because they save developers time by allowing them to abstract out the metadata into a tool-agnostic syntax that a TMS like DTM can then ingest and set as data elements. Whereas once I would have told IT “please set s.prop5 and s.eVar5 to the search term on a search results page, and set s.events to event20” now I can just say “please put the search term in a javascript object such as digitalData.page.onsiteSearchTerm and tell me what object it is.” Then the TMS administrators could easily map that to the right variables from there.

You can see an example data layer if you’d like, or you can pull open a developer console for this very blog and look at the object “digitalDataDDT” to see the data layer that is automatically created from Search Discovery’s wordpress plugin.

Why a Data Layer?

My friends at 33 Sticks also have a great blog post on the subject, but I’ll list out some of the reasons I prefer clients to use a Data Layer. To me, it’s an upfront investment for a scalable, easily maintained implementation going forward. It does mean more work upfront- you have to first design the data layer to make sure it covers your reporting requirements, then you’ll need developers to add that to your site. But beyond those upfront tasks, configuration in your TMS will be much simpler, and it will save you many hours of CSS guess work and DOM scraping, and it may prevent broken reporting down the line.

    Upfront LOE Maintenance LOE
Route Amount of Control Dev Analytics Dev Analytics
Old fashioned “page on code” Medium Heavy Heavy Heavy Heavy
DTM + “Macgyver” Low Minimal Heavy Minimal Heavy
DTM + Data Layer High Heavy Medium Minimal Minimal

Another potential benefit to a Data Layer is that more and more supplementary tools know how to use them now. For instance, Observepoint’s site scanning tool can now return data on not just your Analytics and Marketing beacons, but on your Data Layer as well. And one of my favorite debugging tools, Dataslayer, can return both your beacons and your data layer to your console, so if something is breaking down, you can tell if it’s a data layer issue or a TMS issue.

Ask Yourself

Below are some questions to ask yourself when considering using a data layer:

How often does the code on the site change? If the DOM/HTML of the site changes frequently, you don’t want to rely on CSS selectors. I’ve had many clients have reports randomly break, and after much debugging we realized the problem was the developers changed the code without knowing it would affect analytics. It’s easier to tell developers to put a data layer object on a page then leave it alone, than it is to tell them to not change their HTML/CSS.

How CSS-savvy is your TMS team? If you have someone on your team who is comfortable navigating a DOM using CSS, then you may be able to get away without a data layer a little more easily… but plan on that CSS-savvy resource spending a lot of time in your TMS.  I’ll admit, I enjoy DOM-scraping, and have spent a LOT of time doing it. But I recognize that while it seems like a simple short-term fix, it rarely simplifies things in the long run.

How many pages/page types are on the site? A very complicated site is hard to manage through CSS- you have to familiarize yourself with the DOM of every page type.

How are CSS styles laid out? Are they clean, systematic, and fairly permanent? Clearly, the cleaner the DOM, the easier it is to scrape it.

How often are new pages or new site functionality released? Sites that role out new microsites or site functionality frequently would need a CSS-savvy person setting up their DTM for every change. Alternatively, relying on a data layer requires a data-layer-savvy developer on any new pages/site/functionality. It is often easier to write a solid Data Layer tech spec for developers to reference for projects going forward than to figure out CSS selectors for every new site/page/functionality.

How much link-tracking/post-page-load tracking do you have on your site? If you do need to track a lot of user actions beyond just page loads, involving IT to make sure you are tracking the right things (instead of trying to scrape things out of the HTML) can be extremely valuable. See my post on ways to get around relying on CSS for event-based rules for more info on options.

What is the turn-around time for the developers? Many clients move to DTM specifically because they can’t work easily within their dev team to set up analytics. A development-driven data layer may take many months to set up, stage, QA, and publish. Then if changes are needed, the process starts again. It may be worth going through the lengthy process initially, but if changes are frequently needed in this implementation, you may find yourself relying more on the DOM.

Are there other analytics/marketing tag vendors that may use a data layer? You may be able to hit two birds with one stone by creating a data layer that multiple tools can use.

Have you previously used another tag management system? Often, a data layer set up for a different tool can be used by DTM. Similarly, if the client ever moves away from DTM, their data layer can travel with them.

Does the site have jQuery? The jQuery library has many methods that help with CSS selectors (such as .parent, .child, .closest, .is, .closest…). A CSS-selector-based implementation may be more difficult without jQuery or a similar javascript library.

Who should create my Data Layer?

Ideally, your data layer should be created by your IT/developers… or at bare minimum, developers should be heavily involved. They may be able to hook into existing data in your CMS (for instance, if you use Adobe Experience Manager you can use the Context Hub as the basis for your data layer), or they may already have ideas for how they want to deploy. Your data layer should not be specific to just your Analytics solution; it should be seen as the basis of all things having to do with “data” on your site.

Yet frequently, for lack of IT investment, the analytics team will end up defining the data layer and dictating it to IT. These days, that’s what most Tech Specs consist of: instructions to developers on how to build a data layer. Usually, external documentation on data layers (like from consulting agencies) will be based on the W3C standard.

The W3C (with a task force including folks from Adobe, Ensighten, Microsoft, IBM…) has introduced a tool-agnostic data layer standard that can be used by many tools and vendors. The specifications for this can be found on the W3C site, and many resources exist already with examples. Adobe Consulting often proposes using the W3C as a starting point, if you don’t have any other plans. However, in my experience, generally that W3C is just a starting point. Some people don’t like the way the W3C is designed and most everyone needs to add on to it. For example, folks might ask:

  • why is “onsiteSearchTerms” part of digitalData.page? Can I put it instead in something I made up, like digitalData.search?
  • I want to track “planType”- the W3C didn’t plan for that, so can I just put it somewhere logical like digitalData.transaction?
  • I don’t need “digitalData.product” to be in an array- can I just make that a simple object.

The answer is: yes. You can tweak that standard to your heart’s delight. Just please, PLEASE, document it, and be aware that some tools will be built with the official standard in mind.

The Phased Approach

Many folks adopt a TMS specifically because they don’t want to have to go through IT release cycles to make changes to their implementation. You can still use a TMS to get a lot of what you need for reporting without a data layer and without a ton of CSS work. It may be worthwhile to put a “bare minimum” TMS deployment on your site to start getting the out of the box reports and any reports that don’t require a data layer (like something based on a plugin such as getTimeParting), then to fill in the data layer as you are able. I’d be wary though, because sometimes once that “bare minimum” reporting is in place, it can be easy to be complacent and lose some of the urgency behind getting a thorough solution implemented correctly from the start.

Conclusion

I fully understand that a properly designed data layer is a lot of work, but in my experience, there is going to be a lot of effort with or without a data layer- you can choose for that effort to be upfront in the planning and initial implementation, or you can plan on more longterm maintenance.