amitdusane.com Adobe Analytics Learning

Collect the dataData Layers

Data Layer Design

Open a blank file and start designing a data layer, and the first thing you notice is that nothing pushes back. Call the root abc. Nest six levels deep. Put the product identifier inside the page object. Every one of those choices parses, loads, and collects data exactly as well as the alternative. The browser does not care. Adobe does not care.

That is the whole difficulty of this task. A design mistake here produces no error, no warning, and no failing report. It produces a data layer that works perfectly on the day it ships and costs a fortune eighteen months later, when somebody who was not in the room has to add a field to it.

So the question is never whether a design works. Almost all of them work. The question is which one is still being extended in three years, rather than quietly replaced.

The test a design has to pass, and it is not a technical one

There is a pull toward sophistication in this work, and it is worth naming before it does any damage. You have seen elegant schemas. You can nest deeply, abstract neatly, and name things with real precision. Doing so makes a design look considered, and it makes the person who produced it look like an expert.

Resist it. The expertise runs in the opposite direction.

A data layer design has to pass one test: a business user can read the structure and understand what it holds, while it still satisfies every requirement placed on it. Both halves are load-bearing. Simple but incomplete is not a design, it is a gap. Complete but unreadable is not a design either, it is a liability with good intentions.

Remember who actually reads this thing. The web developer populating the values. The QA analyst opening a console to check them. The business stakeholder validating that the tracking matches what was asked for. And eventually the person who inherits all of it with no context and no access to you.

A design that impresses in a review and cannot be explained to the developer who has to build it has failed at the only job it had.

Which model you are designing for

Two models are in play, and choosing between them happens before design starts. Do You Really Need ACDL? works through that decision in full, and lands on a position worth restating in one line: prefer the least complex model that reliably solves the real problem, which for a great many organisations is a well-designed traditional layer rather than the event-driven one.

This section works primarily in the traditional CEDDL shape, because that is what is running in most implementations and because the design thinking is easier to see when the syntax is out of the way. Where the Adobe Client Data Layer expresses the same idea differently, the mirror is shown alongside.

None of that is advocacy. The useful discovery is that the principles do not change between the two. Only the delivery does.

The nodes are a family tree, not a set of categories

The most common misreading of a data layer is to treat its levels as types. Four levels, so four kinds of thing, the way a site has five sections or a catalogue has ten product categories.

They are not a classification. They are a lineage.

One parent has many children. A child belongs to one parent. That relationship, and not the depth, is what makes a path readable, because it means the ancestry of a value tells you what the value is.

Now the part that matters, because nothing prevents it. You can absolutely write digitalData.page.category.name and digitalData.event.category.name in the same implementation. Both parse. Both collect. A page category and an event category are genuinely different things, so the structure is not even dishonest.

Do not do it anyway.

The same word in two families, and what it costs
Reads cleanly digitalData page interaction pageInfo dropDown every path names exactly one thing Ambiguous page event category category name name the reader must know the parent to read the child

The cost is not technical, which is exactly why it gets waved through. The cost is that a path stops being self-describing. Somebody reading category.name in a rule, a report, or a support ticket now has to trace back up the tree before they know what they are looking at, and they will do that every single time.

Give the two things different names. pageCategory and interactionType cost nothing and never need explaining.

Four levels is a house rule, not a standard

It is often said that a CEDDL data layer has four levels. The specification does not say that. Several objects sit directly beneath the root, including digitalData.pageInstanceID and digitalData.version, which are two levels deep, and the spec explicitly allows extension at varying depths. Committing your own implementation to a consistent shape is still worth doing, because a uniform structure is predictable to read and cheap to extend. Just adopt it as your convention rather than believing the standard requires it, because the difference matters the moment somebody quotes the spec back at you.

Why the root is called digitalData, and why renaming costs more than it looks

The CEDDL root object is digitalData. There is no programming reason for that name. Call it abc and nothing breaks: no error appears, no console warning fires, and Adobe Analytics reports exactly the same numbers.

Keep it anyway, for three reasons that have nothing to do with the code running.

It explains itself. Digital data, collected on digital platforms, for digital analytics. Somebody encountering the term cold can work out roughly what they are looking at, which is more than most variable names manage.

It is discoverable. Open almost any site with Adobe Analytics, type digitalData into the browser console, and the structure appears. That only works because enough people agreed to the same word, and it stops working the moment you decide to be original.

And that is the real argument. A standard you are free to ignore is still worth keeping, because its value was never to you. It goes to whoever arrives next, and it is paid in the time they do not spend asking questions.

The Adobe Client Data Layer works the same way with a different word. Adobe did not invent the array-based model, it standardised an approach that already existed, and its default global object is adobeDataLayer. The name is configurable, which sounds harmless.

Renaming the ACDL object leaves you with two objects, not one

Set a custom name in the Adobe Client Data Layer extension and the original adobeDataLayer is still instantiated, then duplicated into the name you chose. Both exist on the page, both carry the same data, and anybody debugging has to know which one the site code actually writes to. Renaming does not replace the default. It adds a second copy alongside it, and that copy has to be explained to every person who opens the console from then on.

There is no single correct design, which is not the same as anything goes

An automobile company builds the car and publishes guidance on how to drive it. Then people drive. Some quickly, some cautiously, some for adventure, some for the scenery, some using every feature and some who never leave third gear.

Who is driving correctly? Nobody, and all of them. The guidance was never going to settle it, because the guidance was about the vehicle and the driving is about the destination.

Data layer design sits in the same place. The standard defines the vehicle. What you build with it depends on your product, your platform, and the problem in front of you, and a design that is perfect for a retail catalogue may be entirely wrong for a booking engine. There is no arrangement that is correct in the abstract.

Which is not permission to improvise. The conventions below are the ones that survive contact with real projects, and it is worth knowing them properly before deciding which to set aside.

Designing a node, one question at a time

Take a concrete requirement. A visitor selects an option from a dropdown, and that selection needs to be captured. Where does it go?

The temptation is to answer in one move and write something plausible. Answer it as four questions instead, because the questions are where the design actually happens.

Four questions, and the path assembles itself
Question 1 already decided digitalData the root Question 2 what kind of data? interaction page level, or this Question 3 which element? dropDown one of many Question 4 worth knowing? name / module / value not just the value digitalData.interaction.dropDown.value

Question one is already answered. The root is digitalData, decided by the standard, requiring no thought. Move on.

Question two is the one that does the work. Not "where does this dropdown go" but the much larger question hiding behind it: what kinds of data will this site produce at all? Ask it properly and two categories emerge almost immediately. There is data that is true about the page, and there is data about something a person did.

Naming that second category deserves a moment. event, action, activity and interaction are all reasonable candidates. Rule out event and activity first, because both already carry specific meanings in Adobe Analytics, and a data layer node that collides with a platform term will muddle every conversation that follows it. action is available but reads too narrowly, since a mouseover is worth capturing and is not really an action. interaction is generic enough to cover the whole family and collides with nothing.

Question three opens the picture up. Once the category exists, the full inventory becomes visible: link clicks, button and call-to-action clicks, dropdowns, checkboxes, radio buttons, hamburger menus, navigation clicks, mouseover. The element type belongs here, which gives digitalData.interaction.dropDown.

Question four is where most designs go wrong. The natural guess is that the last node holds the selected value. It is the obvious answer and it is a trap, because every element carries more than one fact worth recording. Which control was it. Where on the page did it sit. What did the visitor choose. Put the value at level four and there is nowhere left for the rest.

AttributeWhat it answersInclude it?
nameWhich specific control was thisMinimum set
moduleWhere on the page it sits: banner, footer, side bar, a named formMinimum set
valueWhat the visitor selected or enteredMinimum set
typeDropdown, checkbox, radioUsually redundant, the parent node already says it
positionIndex within a list or carouselOnly when order carries meaning
labelThe visible text, when it differs from the internal nameOnly when the two genuinely differ
destinationWhere a click leadsLinks and calls to action only

Three of those are worth taking as a default set. They answer which control, where it lives, and what happened, and that combination is enough to build a usable report without inventing fields nobody will populate.

Put it together with a real situation. A gender dropdown sits inside an inquiry form, and the visitor selects Male.

One dropdown selection, traditional CEDDL layer
digitalData.interaction.dropDown.name   = "Gender Selection"
digitalData.interaction.dropDown.module = "Inquiry Form"
digitalData.interaction.dropDown.value  = "Male"

The same design expressed through the Adobe Client Data Layer keeps every naming decision intact and changes only how the values arrive.

The identical design, expressed in ACDL
adobeDataLayer.push({
  event: "interaction",
  interaction: {
    dropDown: {
      name: "Gender Selection",
      module: "Inquiry Form",
      value: "Male"
    }
  }
});

That is the quiet reward for designing the hierarchy properly rather than designing for a technology. The structure survived the change of model entirely. A good design is portable, and a design that only makes sense inside one delivery mechanism was never a design in the first place.

Casing: the rule that is not a rule

Look closely at digitalData and dropDown. Neither is lowercase, neither is Title Case, and neither uses underscores. The convention is lower camelCase: begin in lowercase, then capitalise the first letter of every subsequent word. digital plus D plus ata. drop plus D plus own.

Nothing enforces this. Casing has no effect on how data is collected or how reporting behaves. JavaScript is case sensitive, so a layer must be internally consistent or lookups simply fail, but which convention you pick is entirely free.

Pick camelCase regardless, because the specification uses it, the surrounding ecosystem uses it, and consistency is the entire product here.

Then there is the acronym exception, which looks like a lapse in discipline and is not. customerId reads awkwardly and customerID reads correctly, so acronyms keep their capitals. The standard does this to itself: pageInstanceID capitalises the acronym while every neighbouring property stays in plain camelCase. When the specification breaks its own pattern for readability, that is a convention rather than an accident.

PreferAvoidWhy
pageNamepage_name, PageName, pagenameMatches the specification and everything built around it
dropDowndropdown, drop_downThe word boundary stays visible at a glance
customerIDcustomerId, customer_idAcronyms keep their capitals, as in pageInstanceID
loginStatusLoginStatusThe leading character stays lowercase

The rule underneath all of these is the only one that truly matters: choose a convention, write it down, and apply it without exception. A data layer that is ninety percent camelCase is worse than one that is consistently anything, because partial consistency teaches the reader a pattern and then betrays it.

The same discipline, one level down, in the values

Everything so far governs the names. Nothing yet governs what arrives inside them, and that is where the more expensive version of the problem lives, because a field name is written once by one person while a value is written again by whoever ships the next feature.

Two decisions settle most of it, and both have to be written down rather than assumed.

Commit to types. Numbers arrive as numbers, booleans as booleans, arrays as arrays. A price sent as "49.00" and a flag sent as "false" both look harmless in a console, and both fail quietly downstream, because a data element asking whether the visitor is logged in receives the string "false" and finds it perfectly true. Every non-empty string is. The report then shows an authenticated population of one hundred percent, and nothing anywhere has failed.

Enumerate what a categorical field is allowed to hold. A login status field will receive logged in from one team, loggedIn from another, authenticated from a third, and Y from whoever was in a hurry. Every one of those is a separate row in the report. The dimension still populates, which is the problem: it simply cannot be segmented on, and the person who finds that out is an analyst six months later who had assumed the field meant one thing.

Naming the field is the easy half

A specification that lists field names and paths and stops there has documented the part that rarely goes wrong. Carry the type as well, the permitted values for anything categorical, and one more decision teams almost never make explicitly: what absence means. A field that does not apply, a field that applies but is unknown, and a field the visitor deliberately left blank are three different situations. If all three arrive as a missing key, every consumer downstream invents its own reading of the same silence.

What the design looks like when it reaches a developer

A design is not finished when the structure is settled in your head. It is finished when somebody else can build from it without asking you a question.

That artefact is a mapping, and it is deliberately boring: the Adobe variable, the name the business uses for it, what it contains, and the exact path it is read from.

VariableVariable nameDetailsData layer path
pageNamePageThe reporting name of the page, set on every pagedigitalData.page.pageInfo.pageName
eVar1Custom Page NameThe same value in an eVar, so it persists and can carry attributiondigitalData.page.pageInfo.pageName
prop1Custom Page NameThe same value in a prop, for pathing and traffic reportsdigitalData.page.pageInfo.pageName
ChannelSite SectionPDP, PLP, Cart, HelpdigitalData.page.pageInfo.section
prop3Page TypeSearch, Browse, Product Detail, CartdigitalData.page.pageInfo.pageType
eVar8Customer IDYour own internal identifier for a signed-in userdigitalData.account.info.custID
eVar9Website IdentifierBrand or property namedigitalData.page.pageInfo.website
eVar10Login StatusLogged In, AnonymousdigitalData.account.info.loginStatus
eVar11PlatformApp, WebsitedigitalData.page.pageInfo.platform

Two things in that table are worth reading deliberately.

The first three rows point at the same path. That is not duplication and it is not a mistake. One data layer field routinely feeds several Adobe variables, because a prop and an eVar do different things with the same value. The data layer describes the site; the variables describe what you intend to do with it. Keeping those two concerns separate is what allows you to add a new eVar later without touching a line of site code.

The second is the row carrying a customer identifier, and what goes into it is a deliberate decision rather than a convenience. Use your own internal identifier, never a raw email address or phone number. A data layer is a global object on the page, readable by every script the site loads, including tags nobody on your team wrote, so a contact detail placed there has effectively been handed to all of them. The reporting is identical either way, which makes the safe choice free.

An internal identifier still carries an obligation, because it identifies a person the moment it is joined to your own systems. It has to be labeled before Adobe can act on it in a deletion request, and Privacy and Data Retention covers that labeling, along with the silent failure when it is missing.

The path column is the contract, and it is the only column developers need

Everything to the left of the path belongs to analytics: which variable, what it is called in reports, what the business expects to see. Only the rightmost column is a build instruction. Keeping that boundary visible is what stops a mapping document turning into a negotiation, because the developer can be handed one column and be certain it is complete.

The equivalent under the Adobe Client Data Layer swaps the path for a state read, so digitalData.page.pageInfo.pageName becomes adobeDataLayer.getState("page.pageInfo.pageName"). The mapping document keeps its shape, and so does every naming decision inside it.

What you have now

Every rule in this section is a readability rule wearing technical clothing. Nothing here is enforced, nothing produces an error, and a design that ignores all of it will collect data perfectly well on launch day. That is precisely why the discipline has to come from you.

The nodes are a lineage rather than a set of categories, so a path can describe itself. The standard names are worth keeping because their value accrues to whoever arrives after you. A node is designed by asking four questions in order, and the fourth one is the one that catches people, because an element is never just its value. One casing convention, applied without exception, and the same insistence carried down into the values, where types and permitted values decide whether a field can be reported on at all. And a mapping so plain that a developer needs a single column from it.

The test at the start still applies to all of it. If a business user can read the structure and follow what it holds, and it still meets every requirement, the design is good. If it needs you in the room to be understood, it is not finished, however elegant it looks.

A design is only worth what gets read from it. The mechanism that does that reading in a tag management system is the data element, a named reference that points at a path and hands its value to rules without any of them knowing where it came from. Data Elements covers how that indirection works and why bypassing it costs you later.

Need implementation steps?

This article focuses on the concepts, architecture, and practical guidance behind the topic. For the latest UI walkthroughs and step-by-step implementation instructions, use the links below. They leave this site and open Adobe's own documentation in a new tab.