The Adobe Client Data Layer

I have pushed this article back so many times that I feel bad for it. So even though one part of the story isn’t there yet, I’ll publish it now. (Update, the Extension is now publicly available!)

The story began with me moving to Switzerland and the Basel office. This office came to Adobe via the acquisition of Day Software, and Day Software was the creator of what is now known as Adobe Experience Manager, or AEM.

In short, I came into an office full of people working in content management, and I was the odd one out for a couple of months. The good part about that is that I got to know a lot of people, and I learned a lot about how AEM works, and how its creators think.

A long-term result of it was that I was part of the discussions about the Adobe Client Data Layer at an early stage, and I have been wanting to write about it for a pretty long time.

In the meantime, during a hackathon, 3 of my colleagues wrote a Launch Extension to make usage of the ACDL easier. As of October 19, the Extension is in the pipeline for release, and I originally wanted to hold back with this article until it was available in the Launch Extension Catalog.

It’s really close to release, in fact. But I thought so before, at least two times, and so this time, I won’t be fooled again.


The Adobe Client Data Layer (ACDL) is an Event-Driven Data Layer (EDDL), built by a team around my colleague Gabriel Walt. They built it along with the Core Component Library for AEM.

The point of the Core Component Library is to try and standardise things. If you have read more than one article here, you know that I am a big fan of that, or rather of simplifying, which the Core Component Library does, too.

Gabriel and team did the right thing: they went straight for an EDDL, ignoring the (not so) current W3C CEDDL standard.

The ACDL is fairly flexible in terms of format. It has been built to be easy for developers to use. As with all EDDLs, data is added into the ACDL using a push() method, and you can get data out using a getState() method.

There is a lot of documentation available on the ACDL: The ACDL has its own ACDL Wiki page. The chapter on Setup is pretty straight-forward, and the Methods chapter is pretty verbose. I really like that you can push functions, and how the ACDL handles them.

Using the Adobe Client Data Layer with the Core Components talks about installation with AEM, and about events and data provided by the Core Components. Using the Adobe Client Data Layer with AEM Core Components is very similar, but contains a short video, too. There was a session at adaptTo this year. I’ll add a link to the recording when it is available.

And since the ACDL is open-source, you can use the source, Luke.

I’ll just point out two more blog articles, and then I’ll get to the point.

First, Jim Gordon wrote The Adobe Client Data Layer (ACDL), an article looking at the ACDL, and the Extension (which at this point was not released, and it is also currently not available privately, for reasons that I do not want to go into is now available). Note that you will be able to simply add the Extension to your Properties from the Catalog now.

Second, my colleague Julien Piccini wrote The Event Driven Data Layer revolution, in which he compares the Google EDDL implementation with the ACDL, on a high level. The concept is always the same, and much of the below applies to both.

Right, with that out of the way, you and I are wondering: what on Earth can I add to the above? Sounds like a lot of stuff has been said, right?

Good Practice

I still think that this blog is in a very small niche: trying to explain analytics/marketing topics to the people who have to help implement.

And so I want to dwell on two things that you (the developer) will do with the ACDL, so that your friendly marketer gets all the data she needs:

  1. Data that is sent to Analytics on “page load” (whatever that may be in your case), and
  2. how to handle user interaction, like clicks.

Both of those use cases can be simple, but depending on how your site works, there can also be some brutal trade-offs to be made for both.

In the spirit of acknowledging the complexity of this, I shall therefore not talk about “best practice”, instead I’ll tell you what I think is good practice.

Page Load

Using Analytics used to be fairly straight-forward in the pre-TMS days. People discussed whether the tracking call should be triggered at the top of the page, or at the bottom.

The former would give you more tracking, because sometimes people navigate away quickly, and tracking at the bottom might be too late. Conversely, tracking at the bottom has less impact on page load time, and that’s why I would always recommend it. These days, though, that doesn’t really matter anymore.

With DTM came the possibility of tracking at specific stages of the page loading, such as “Page Top”, “Page Bottom”, “DOM Ready”, and “Window Loaded”.

We usually tracked at “Page Bottom”, or at “DOM Ready”, and when Launch came, and we started to load Launch asynchronously, we settled for “DOM Ready”.

Given how complex a simple web page can be these days, and that people start to move away from monolithic CMS, taking it this easy is no longer the best thing to do.

Almost all pages load at least a part of their content asynchronously. The go-to example is the product detail page on a retail site, which gets some, if not all of the product data from some back-end system. The CMS serves an empty page with a product ID, and Javascript or some other technology pull in the missing elements and display them.

This applies to the data layer, too, and it is one of the reasons why an EDDL is so important.

It is likely that your data layer will contain the product ID or sku at an early stage of loading the page, but things like product name, price, or availability may only be available in the data layer much later.

So, we analytics people wonder, at which point do we track?

We want to track as much data as possible, but we also do not want to wait too long, because at some point, the visitor will move on.

One answer is to change the way that Analytics does tracking. If I had a Franc Swiss for every time some AEM person asked me “can you not just, like, keep the page view tracking hit, like, open, so we can add data when it comes available?”, I would have enough money for a chocolate bar or so.

My answer to that has always been “sure, but Analytics doesn’t work that way”, until I saw Platform and the Web SDK, and now I say “well, you can do that once that customer is fully on Platform”.

Another answer would be for the analytics people to sit down with development, and to decide which data points are considered vital, in which order those usually arrive, and then just track when they’re all there.

Yet another answer would be to make this explicit, as in: dev pushes some “page data complete” event to the data layer when it is, well, complete, and analytics folk use that event to trigger tracking.

How you eventually do it will depend on your site, and how much async stuff is really going on on it. In general, I would tend towards ‘explicit’, though, and not just because it is a tiny bit ambiguous.


A great thing about using a TMS and an EDDL is that you can pretty much separate how dev and analytics teams work, and you end up with an interface between their spheres of influence that is pretty visible, both in the data layer and the Events and Rules in the TMS. I like that.

An open question, right now, is how does the TMS react to data layer changes?

For Launch, that is where the Extensions come in, be it the Data Layer Manager by Search Discovery, or the aforementioned and not yet publicly available Adobe Client Data Layer by Adobe Consulting.

Both can monitor the data layer for events, generic or specific, and turn those into Launch “Event Types”, which are used to trigger Rules (see the “Event Type” chapter in Launch – Make an Extension – Techniques & Types).

They also both provide easy access to the elements inside the data layer via Data Elements, although they go about it in slightly different ways.

So, tracking data into Analytics on page load with an explicit event being pushed into the data layer boils down to creating 1 Event, Data Elements for your data, plus 1 Rule that uses the “Analytics – Set Variables” and “Analytics – Send Beacon” Action Types.

That’s it.

If you can agree with your developers, if they are willing to push an event, then do it like this.


This one is actually really straight-forward, with one issue: timing

So here’s the setup: a page loads, and there is a carousel on it, which rotates a bunch of different offers into the page. Those offers can be clicked, of course, and so your friendly marketer would like to see two things: a) how often have offers been loaded, and how often are they being clicked. For any offer, she can then look at the click-through rate (# of clicks on that offer divided by number of times it was shown).

For you, that means: when the carousel loads, list all of the offers it contains into the data layer. The analytics person will use that to track which offers were shown. You also need a click handler that will write the name or ID of the clicked offer into the data layer when the visitor clicks. Again, the analytics person will use that to track which one was clicked.

The timing issue arises because you want that tracking to actually happen before the browser ditches the current page and loads the next.

So, please, in your click handler, suppress the default, and instead, use setTimeout() to redirect the browser after a short wait. 500ms work ok.

Thank you!


A good catch from Lukas: you can, and should, enable “[x] Run rule components in sequence” setting on your Launch Property. That way, the Actions will run one after the other, and there won’t be any race conditions.

See Rule Components Sequencing for details.

“Run rule components in sequence” Setting in Launch

4 thoughts on “The Adobe Client Data Layer

  1. Hi,

    Great article as always Jan.

    I justed wanted to chime in on the click tracking/click handling where you advise to redirect the page with a settimeout to allow the tracking to complete. An alternative solution I like to deploy is to set the tracking on mousedown which gives about 300ms between the mousedown event and the click event being processed by the browser. This is sometimes easier to manage than working with timeouts. There might be false positives in the click for people doing a mousedown and then do not click anymore but that percentage is negligible as far as I have seen.

    Best regards,



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.