Adobe Launch

Functional Programming in Launch

Event-Driven Data Layer

The start of that new idea was the implementation of the event-driven data layer for one of the client. This new approach, that has been discussed many times by Jim Gordon, was considered by the client.

The question that comes when you use this approach is the way that you will deal with the different objects that are being sent at the same time of your event.
The big idea of that approach is that a copy of the data layer is being sent with each event. Sometimes, you may have several events firing within a very short time frame and you would need to handle the different states of the datalayer for each event.

If you use a global data layer object to fill your request, you may come into the problem that your datalayer doesn’t reflect the state that the datalayer had during its event.

In the graphical representation above, I tried to explain that the Event 1 and 2 are both making a change to the Data Layer. Only few milliseconds happen for both events. Either with the Data Layer handler from Google or with a specific event attached to each action, they both calls the TMS (Tag Management System).
As the TMS is looking for the data layer to fills the different request, it can happen that it is looking at the state number 2 as the state 1 is not available any more.
This can create an issue as the data you are capturing may not reflect the state of Event 1.

Solving timing discrepancy

There are several ways that you can solve this time decay, or time discrepancy between event and data layer state.

Google Data Layer Helper

Google has released (or more exactly open-source) the Data Layer Helper code recently.
You can find it here : https://github.com/google/data-layer-helper
I have been encouraged to look at it by different other consultants and after playing with it, it seems that it actually solve lots of issue by itself.
For our current issue, the Data Layer is kept in a list-type (or array-type in JS) object and you can always find any previous state.
So if you have a way to know which state you want to look back, you can re-create that state directly by using the datalayer helper.

Event Detail

The Google Library also provides this type of possibility but it is easy for your own library to build this type of binding anyway. When the event change your data layer, you send a copy of the data layer with the event itself (with the green arrow). Usually the objects are attached within the object details. You can find more detail in the MDN documentation.

In our case, we have decided to go with a copy of the data layer in the event detail.

Handling Event Detail

Launch provide different way to deal with event detail. By the way, the Direct Call Rules in Launch are now quite similar in that note. You can also pass an object to a direct call and handle it within the Tag Management System. Just in case you didn’t know it : https://helpx.adobe.com/analytics/kb/direct-call-rule-with-additional-parameters-in-adobe-launch.html
Therefore I consider events and direct call rules similar in the next sections.

As described by the Direct Call Rule article above, you can directly reach the event.detail object within each rules. If you are using Adobe Analytics on your event, which is the case we are interested in, you can also probably directly reach with the doPlugins probably because it is fired at the same time.
However, the doPlugins is being reached on each click on the page, so be careful how you are handling that. I wouldn’t recommend to put an event reader there, as it is a sensitive place… but feel free to try if it answers your problem.

Spaghetti Code possibility

One of the option is clearly to use the Custom Code option within your Rule action in order to reach that object. It is possible to handle the different data layer state by doing that.
The problem for that it is that it is creating lots of code to handle the different elements (eVars, props and events) that you want to capture.
If you have the same way of populating those elements with your data layer structure, then you need to replicate that code over and over into each of your rules.

Also, imagine that you want to track a dimension in multiple rules. When you need to change that dimension logic, you would need to go into each of the rules and change the code there.
Thanks to the python wrapper for the Launch API, it is now easy to find where each dimensions is set within each of your rules but still… it will be error-prone and quite cumbersome (yes… it was self-promotion 😀 ).

Also, I would like to avoid this kind of spaghetti code implementation. Lots of code that are being written within one rule and you don’t exactly what it is doing.
Fair enough, you can comment and try to have clean code but I honestly never seen that happening to any implementation… especially if your code is realized and maintain by (different) agencies. But if you feel confident that it would not be the case for you… feel free to do it, then 6 month later, try to explain what the code in each rule is doing.

The best way to deal with this kind of problem (centralization, deduplication of code, easy access) would be the data elements. it has been built for that purpose….the problem is that you cannot make your data element attached to the event object.
They don’t belong to the same scope unfortunately, you would need to have the data element to be linked somehow with the events, at the time that the event happen. It just doesn’t work that way….

or is it ? 😉

Data Element as functions

At some point, it seems that there was 2 possibilities to realize that.
Either I was going to build an extension in order to have a clean way to realize this tracking within my rules or I was going to use spaghetti code.

An extension is always nice, I do love extensions but I am feeling that people tend to create extension for things that already exists, or things can you already can do with the current supported Launch capabilities. Extensions can be a good way to provide additional functionalities to Launch, whenever current options are not suiting your needs. However, I feel that they under-estimate the amount of time and the effort needed for creating a good extension and support it in the future.

Following that dilemma, I started to think of a way to attach data element to event object. 2 main reasons :

  1. Data Elements centralize information
  2. Data Elements abstract the implementation details

If we could use the data elements to realize the implementation, you could centralize some functionalities and if you need to change the functionality, you have only one place to change.

The second reason is that the data elements can exist as an abstraction for some functionalities in your code. You can define what this data element can do and it will not be mixed with the other data elements. Therefore, you won’t create dependencies (or at least limit them) by separating the code into different data elements or functions.

It is the basis of software programming but it can be quite hard to have this approach in a tool.

Data Elements with JS objects

When realizing my different tests, I realized that the Data Elements returns any JavaScript object that has been passed to them. I think that it is not uncommon to have the complete data layer in a data element or to have a list in a data element at some point. You may have experienced this kind of implementation.

One of the paradigm of JavaScript is its Object-oriented programming and therefore, any element can be an object in JavaScript. Therefore, you can technically define function as object and return that object itself, which will be a function…

OK it may be a bit hard to understand if you don’t realize “semi-advanced” JS programming but I think an example will help you to understand.

In the Data Element itself, we will create function that will be returned by that data element. We can create the data element as the following :

/*inside my data element - "myFunction" */
function myFunction(something){
if(typeof(something) == 'string'){
    var element = something.toLowerCase()
}

else{
    var element = 'not a string'
}
return 'This is '+ element
}
return myFunction

As you can see, you return the function itself with the data element, therefore, you can use that function later on.

/*in a rule*/
s.eVar1 = _satellite.getVar('myFunction')('awesome');//will return 'This is awesome'

I think that now you start to realize how you can use that with the event.detail object.
By passing the event.detail object (or any part that is interesting), you can abstract the manipulation of the event.detail to a data element and clean you implementation.
Having a centralize place to take care of all the implementation logic.

You can separate the rule logic from your data layer extraction logic. If you have a consistent data layer passed at the same time than your event, it can be quite powerful.

I find this solution quite elegant and quite ugly at the same time to be honest… It will make your implementation look nicer on the outside but if you are doing ugly things within your data element, then it is just not really helping. You have the advantage of not having to maintain an extension and use pre-existing tools to work with your implementation.

The function can take arguments but you can also defined fallbacks.

function pageCat(datalayer){
var datalayer = datalayer || window.digitalData || {};
var pageCategory = datalayer.page.category.pageCategory ||'n/a';
}
return pageCat

On the example above, you can pass an argument but if the argument doesn’t exist, you can look for the global datalayer as fallback.

I hope this article was helpful to understand functional programming with Launch Data Element. I know it is a bit strange but I feel that it came be helpful for some projects.

Leave a Reply

Your email address will not be published. Required fields are marked *