window.digitalData = { page: { name: "Home", type: "homepage" }, user: { loginStatus: "out" } }; Adobe Launch Data Elements Adobe Analytics eVars · props Data Layer Design for Adobe Launch

Key takeaways

  • The data layer is a contract between analytics and engineering — design it before any implementation begins
  • Push the data layer object before the Adobe Launch embed code loads on every page
  • Use a consistent object hierarchy: page, user, product, cart — and never flatten everything to the top level
  • Event-driven data layer pushes for interactions are cleaner than DOM scraping in Launch rules
  • Version your data layer schema and document changes — it is infrastructure, not an implementation detail

The data layer is the single most important piece of infrastructure in any Adobe Analytics implementation. It is also the most frequently skipped. Teams jump straight into Adobe Launch, start writing rules that scrape values off the DOM, and six months later have an implementation that breaks every time a developer changes a CSS class name or rewrites a page template.

I have audited dozens of Adobe Analytics implementations. In every case where data quality problems existed, they could be traced back to a weak or missing data layer. This guide covers how to design, implement, and maintain a data layer that makes your Adobe Launch implementation reliable, scalable, and easy to hand over.

What a data layer actually is

A data layer is a JavaScript object that lives on every page of your website and exposes structured, consistent information about the page and its context. It is the bridge between what your website knows and what your analytics tools need to know.

Think of it as an API that your website publishes for analytics and marketing tools to consume. The website owns the data. The data layer makes that data available in a predictable, structured format. Adobe Launch reads from it. Adobe Analytics, Adobe Target, and any other tags consume it through Launch.

Pro Tip

The data layer should be treated exactly like a public API. It has a schema, it is versioned, it has documentation, and changes to it go through a review process. The moment you treat it as an afterthought is the moment your analytics data becomes unreliable.

Why it matters specifically for Adobe Launch

Adobe Launch reads values through data elements. Data elements can be configured to read from multiple sources — CSS selectors, JavaScript variables, cookies, query strings, or a data layer. Of these, only the data layer gives you values that are:

  • Stable — values do not change when engineers update markup or CSS
  • Intentional — values are explicitly set by the engineering team, not inferred from UI elements
  • Available early — values are present before the DOM finishes rendering
  • Testable — values can be validated in console before Launch even fires
Data Layer vs DOM Scraping — Reliability Comparison Data Layer Data Element Launch Rule → Analytics ✓ Stable — survives markup changes · Always available · Intentional DOM / CSS CSS Selector Launch Rule → Analytics ✗ Breaks on markup changes · May be empty · Fragile Every audit I run finds broken DOM-scraping data elements. The data layer path never breaks.
Fig 1. — Data layer data elements are resilient to markup changes. DOM-scraping breaks every time engineers update the page.

Designing the schema

The data layer schema should be designed before any implementation work begins — by the analytics team, in collaboration with engineering. The schema defines:

  • Which objects exist (page, user, product, cart, etc.)
  • Which properties each object contains
  • What data type each property holds (string, number, boolean, array)
  • Which pages populate which objects
  • What the default/empty value is when data is not available

A well-structured schema uses a clear hierarchy rather than a flat structure. Here is the difference:

JavaScript — Flat structure (avoid this)
// Hard to read, no clear ownership, naming collisions likely
window.digitalData = {
  pageName: "Home",
  pageType: "homepage",
  userId: "",
  loginStatus: "logged-out",
  productId: "",
  productName: ""
};
JavaScript — Hierarchical structure (recommended)
// Clear ownership, easy to extend, maps cleanly to eVars
window.digitalData = {
  page: {
    name:     "Home",
    type:     "homepage",
    section:  "marketing",
    language: "en-IN"
  },
  user: {
    loginStatus: "logged-out",
    userId:      "",          // hashed — never PII
    segment:     ""
  },
  product: {                        // populated on product pages
    id:       "",
    name:     "",
    category: "",
    price:    0
  },
  cart: {                           // populated on cart/checkout
    items:  [],
    total:  0,
    itemCount: 0
  },
  site: {
    environment: "production",
    version:     "3.1.0"
  }
};
Warning

Never store personally identifiable information in the data layer. No email addresses, names, phone numbers, or raw user IDs. If you need to track users, use a hashed or anonymised identifier only. The data layer is accessible to anyone who opens DevTools on your site.

Page load data layer pattern

The data layer must be pushed before the Adobe Launch embed code. This is the most important timing rule. If Launch fires before the data layer is populated, data elements will return empty values on the first event.

1

Push the data layer object in the <head>

Place the data layer initialization as the first script in your page's <head> — before GTM, before Launch, before anything else. This guarantees values are available when Launch reads them.

2

Populate values server-side when possible

The most reliable data layer values come from the server — page type, login status, product IDs, prices. These are known at render time and never depend on JavaScript execution completing. Use client-side JS only for values that genuinely are not available server-side.

3

Use empty strings, not null or undefined

When a property has no value for a given page, set it to an empty string — never null, undefined, or omit the key entirely. Launch data elements will return undefined for missing keys, which can cause eVar values to be "(not set)" in your reports.

4

Initialize every property on every page

The full schema should be present on every page, even if most properties are empty strings. This prevents data from the previous page persisting in memory on single-page applications.

HTML — Correct page load order
<head>

  <!-- 1. Data layer FIRST -->
  <script>
    window.digitalData = {
      page:    { name: "Product:Running Shoes", type: "product" },
      user:    { loginStatus: "logged-in", userId: "u_8f3k2" },
      product: { id: "SKU-4421", name: "Trail Runner X", price: 4999 }
    };
  </script>

  <!-- 2. Adobe Launch embed code AFTER data layer -->
  <script src="//assets.adobedtm.com/your-launch-embed.min.js"
    async></script>

</head>

Event-driven pushes for interactions

The page load data layer covers page-level context. For user interactions — button clicks, form submissions, video plays, add-to-cart — you need event-driven data layer pushes. These are additional pushes that fire when the interaction occurs, adding interaction-specific data to the data layer before Launch fires its rule.

JavaScript — Event-driven push (Add to Cart)
// Fired by your engineering team when user clicks Add to Cart
document.querySelector('.add-to-cart-btn').addEventListener('click', function() {

  // Push interaction data to the data layer
  window.digitalData.event = {
    name:     "addToCart",
    category: "ecommerce"
  };
  window.digitalData.cart = {
    lastAddedProduct: {
      id:       "SKU-4421",
      name:     "Trail Runner X",
      price:    4999,
      quantity: 1
    }
  };

  // Trigger a custom event for Launch to listen to
  document.dispatchEvent(new CustomEvent('digitalData:addToCart'));
});

In Adobe Launch, create a rule that listens for this custom event:

Adobe Launch — Rule listening to data layer event
Rule name: Event — Add to Cart

Event:
  Type: Custom Event
  Name: digitalData:addToCart

Actions:
  1. Set Variables
     event1 = 1                          (Add to Cart event)
     eVar5  = %DL - Last Added Product ID%
     eVar6  = %DL - Last Added Product Name%
  2. Send Beacon (s.tl())

Reading the data layer in Adobe Launch

In Launch, configure your data elements to read from the data layer using the JavaScript Variable type or the Data Layer type if you are using the Adobe Client Data Layer extension.

Adobe Launch — Data Element configuration
Name: DL - Page Name
Type: JavaScript Variable
Path: digitalData.page.name
Default value: (empty)
Duration: None

Name: DL - Login Status
Type: JavaScript Variable
Path: digitalData.user.loginStatus
Default value: (empty)
Duration: None

Name: DL - Product ID
Type: JavaScript Variable
Path: digitalData.product.id
Default value: (empty)
Duration: None
Pro Tip

Always set Duration to "None" on data elements that read from the data layer. This forces Launch to re-read the value fresh on every rule execution rather than using a cached value from a previous page — which is critical on single-page applications where the URL changes but the page does not reload.

Naming conventions

Consistent naming across the data layer, data elements, and eVar mapping is what makes implementations maintainable. Here is the convention I use on every engagement:

Layer Format Example
Data layer key camelCase, nested objects digitalData.page.name
Launch data element DL - [Object] [Property] DL - Page Name
Launch rule [Trigger] — [Action] Page Load — Send Beacon
eVar mapping eVar[N] = [DL element] eVar1 = %DL - Page Name%
Custom events digitalData:[eventName] digitalData:addToCart

Document this convention in a shared specification that both analytics and engineering have access to. The spec should be a living document — updated every time the schema changes, treated with the same rigour as API documentation.

Common mistakes

  • Pushing the data layer after Launch. If Launch loads first, it fires before your data is available. All your data elements return empty on the page load event. Always: data layer first, Launch second.
  • Using null or undefined instead of empty strings. JavaScript Variable data elements return undefined for null/undefined values. In eVars this shows as "(not set)" which pollutes reports and makes filtering impossible.
  • Not reinitialising on SPA route changes. Single-page applications do not reload the page on navigation. The data layer from the previous route persists unless you explicitly reset it. Push a fresh data layer object on every client-side route change.
  • Storing PII in the data layer. Email addresses, names, and phone numbers in the data layer are visible to anyone who opens DevTools. Use hashed IDs only.
  • No documentation or versioning. When the data layer is undocumented, every developer interprets it differently. Three months later nobody knows what half the properties mean or which pages push them.
  • Having engineering own the schema without analytics input. Engineers will build what makes sense for the application. Analytics needs the schema to map to business questions. The spec must be a collaboration — analytics defines what is needed, engineering defines what is feasible.

Data layer checklist

Use this before signing off on any data layer implementation:

  • Data layer is pushed before the Launch embed code on every page
  • Full schema is present on every page — no missing objects
  • Empty values use empty strings, not null or undefined
  • No PII stored in any data layer property
  • Product and cart objects are populated correctly on relevant page types
  • Custom events dispatch correctly and Launch rules listen to them
  • SPA route changes trigger a data layer reset and re-push
  • Schema is documented and version-controlled
  • All Launch data elements use Duration: None
  • Data layer values validated in console before Launch QA begins
AB
Abhinav Bhargav
Founder, MetricByte Consulting · Adobe Certified Master — Analytics Architect

8 years implementing and auditing analytics programs across Adobe Analytics, AEP, GA4, and GTM for enterprise organizations. Founder of MetricByte Consulting. Connect on LinkedIn →