This article will show you how to set up an independent “vendor-specific” Event Driven Data Layer(EDDL) and how to process events within the data layer. A few example code is provided, so you can build your own data connectors.
- Learn how to set up an independent Event-Driven Data Layer.
- Learn how to attach an event listener to process the events in the data layer.
- Using the Google Data Layer Helper library.
- Google tag manager data layer
Why is it still relevant?
The data Layer is still relevant today and even more important seeing the recent focus on the quality of first-party data(Due to strict data regulations)
A structured Event-Driven Data layer(EDDL) including a mechanism that enables you to process and listen to events in the EDDL, can be very powerful when you are planning to create an abstraction layer between your website/app and CDP or client-side data collection tool. When:
- When you want to take full ownership of your data layer and organization do not want to depend on vendor-specific code and/0r requirements.
- when not using Tag management
- Using data collection tools or tag management systems that do not have an event-driven data layer mechanism in place.
- You want to create your own data collection library/script (for example to provide data to Google Tag Manager Server without using the
gtag.js
library or client-side GTM).
What is an Event-Driven data layer?
The term Event-Driven data layer gained popularity through the efforts of Jim Gorden (Jimalytics). As mentioned, there are already a lot of good articles written about the workings and benefits of the EDDL. So I would recommend checking out the following articles first:
- The Event-Driven Data Layer by Jimalytics.
- Event Driven Data Layer guide by Search Discovery.
The Event-Driven Data Layer itself basically is just a plain Javascript array (digital data in the example below), containing (event) objects. Think of page views, clicks, or purchases. The Javascript array is available at the window of the scope.
Example:
window.digitalData = window.digitalData || [];
// Pageview event
digitalData.push({
"event": "page",
"page_type": "product_detail",
"product_id": "12345",
"product_name": "Bata shoes"
// ...
});
// Purchase event
digitalData.push({
"event": "purchase",
"transaction_id": "777",
"product_id": "12345",
"product_name": "bata shoes"
// ...
});
You can structure the events and properties any way you like so that it nicely fit your type of business. Keep in mind, consistency is key!
When such a data layer is in place, one can write some code or use existing libraries to process the events pushed into the data layer array and attach listeners to it. The listeners can be used to build connectors or wrappers around vendor-specific tracking scripts, so you can map your data layer variables to vendor-specific requirements (in one place).
Some common use cases:
- Connect event listeners to the data layer (e.g. Tag Management Systems/tracking script connectors)
- Connect data validators (e.g. JSON schema validation)
- Transform data to specific formats/business requirements before data is sent to data collection or TMS tools.
- Switch listeners based on different platforms or environments, but using the same data layer. Think of parts of your website that are loaded in a Webview.
The benefits of using an EDDL
But what are the benefits of an EDDL compared to (vendor-specific) data layers and collection setups?
- No vendor-specific knowledge is required for developers (e.g. vendor libraries), plain Javascript arrays, and objects (except for building the connector itself).
- No vendor lock-in/vendor agnostic, swap out vendors (client-side TMS / tracking solutions) more easily.
- Data layer structure not tied to vendor-specific requirements.
- Asynchronous
- Excellent fit for single-page / event-driven applications.
Vendor Specific What?
As you can see in the example above, besides (optional) event object structure, there isn’t much vendor-specific logic involved. Since GTM uses the same concept, you could say that GTM already uses an “independent” data layer (besides the recommended event structure).
But, Google Tag Manager isn’t the only TMS used (yes, really). Think of Tealium, Adobe or Segment. But we also have data collection scripts that can be implemented without a TMS, such as the gtag.js
library (and becomes relevant if you don’t want to use client-side GTM to implement server-side GTM for example).
In many cases, these vendors require you to implement vendor-specific code. Some examples:
Tealium iQ (TMS)
A Tealium iQ pageview:
utag.view({
"tealium_event": "product_view",
"page_type" : "product",
"product_id" : ["12345"],
"product_name" : ["Bata shoes"]
});
Adobe
Adobe recently (2020) launched it’s own event driven data layer library, called ACDL, so bad example.
gtag.js
A gtag.js pageview:
gtag("event'" "page_view", {
"page_title": "<Page Title>",
"page_location": "<Page Location>",
"page_path": "<Page Path>",
"send_to": "<GA_MEASUREMENT_ID>"
})
As you can see, there is a lot of vendor-specific code involved. The point here is that you don’t want is to implement such vendor-specific code all through your website or app. So, creating an abstraction layer would be a wise approach.
Listening and processing events in the data layer
A good example of a data layer “listener” library is the Data Layer Helper library by Google (also used in GTM). We will use this library in the examples below.
The Data Layer Helper library will:
Firstly, check out the GitHub repo of the Data Layer Helper. The library is documented pretty well.
- Process events passed into the data layer (
digitalData.push({ .. })
)- Activate listener functions (connectors) when new events are pushed into the data layer
- Process (historical) event already present in the data layer before the library is activated.
- Merges event data (object) into a data model (object)
You can add the library to you application easily;npm install data-layer-helper 2// or 3yarn install data-layer-helper
And import the package
import 'node_modules/data-layer-helper/dist/data-layer-helper';
Another option is to host the minified data-layer-helper.js a version of the library somewhere and include it in your application.
Let’s move on to the examples
Logging events on the console
The first example will just log the events pushed in the data layer to the (browser) console. It nicely demonstrates the capabilities of the library.
// Make sure to include the Data Layer Helper library first
window.digitalData = window.digitalData || [];
// Pageview event
digitalData.push({
"event": "page",
"page_type": "product_detail",
"product_id": "12345",
"product_name": "Shiny red shoes"
// ...
});
const DigitalDataHelper = new DataLayerHelper(digitalData);
function listenerLogToConsole(model, event) {
console.log(event);
}
const DigitalDataHelper = new DataLayerHelper(digitalData, {
listener: listenerLogToConsole,
listenToPast: true, // Process events already in the digitalData array before initializing the library.
});
Now, when you execute the code, you should see the pageview events in your browser console.
Tealium iQ connector
The second example shows you how to create a wrapper function around Tealium iQ-specific code, so it is activated based on events within the data layer.
Tip: It’s perfectly possible to include the data-layer-helper.js script AND the listener function in a Preloader extension within Tealium itself. The benefit is that you know for sure that Tealium is loaded before activating the listener (+ easy to edit the listener function within Tealium itself).
<!-- Data Layer Helper library -->
<script type="text/javascript" src="data-layer-helper.js"></script>
<!-- Tealium Universal Tag -->
<script type="text/javascript">
// Declare datalayer
window.digitalData = window.digitalData || [];
// .. Populate datalayer
// digitalData.push({ .. });
// Tealium config overraide: disable default pageview `view()` on load
// To prevent duplicate pageviews, since the page event will trigger a pageview
window.utag_cfg_ovrd = {
noview: true
};
// Tealium Universal Base Tag
(function(a,b,c,d) {
a='//tags.tiqcdn.com/utag/ACCOUNT/PROFILE/ENVIRONMENT/utag.js';
b=document;c='script';d=b.createElement(c);d.src=a;
d.type='text/java'+c;d.async=true;
a=b.getElementsByTagName(c)[0];a.parentNode.insertBefore(d,a)})();
// Data layer listener function: Tealium connector
// Tip: You can implement this code directly in the front-end OR add the code as a preloader extension within Tealium
function listenerTealium(model, event) {
// Declare utag_data / UDO (Tealium datalayer)
window.utag_data = window.utag_data || [];
// Tealium specific transformations
var _event = event;
var _model = model;
// Mapping digital-data-queue events to Tealium
if (typeof _event.event != 'undefined') {
switch(_event.event) {
case "page":
window.utag_data = _event;
window.utag.view(window.utag_data, function() { window.utag.DB("digital-data: Event: \"" + _event.event + "\" to utag.view()"); });
break;
default:
// Using the model (instead of event) to populate event parameters, so page properties are available within the event.
window.utag.link(_model, function() { window.utag.DB("digital-data: Event : \"" + _event.event + "\" to utag.link()"); });
}
} else {
// No event property set
}
}
// Init Data Layer Helper
var DigitalDataHelper = new DataLayerHelper(digitalData, {
listener: listenerTealium,
listenToPast: true, // Process events already in the digitalData array before initializing the library.
});
</script>