Event Detection: From DTM To Launch
Recently, a question came up in the Measure Slack channel that we’ve heard far too often. Paraphrasing, it went something like this:
I’ve set up a rule in Adobe DTM that should trigger when a user clicks on a particular table cell, but DTM never seems to detect the click. Any ideas on how I can get DTM to detect the click? I noticed our app has its own click listener on the table cell and inside the handler we have
As this user experienced, sometimes DTM has a hard time detecting when an event has occurred. Let’s see why this happens in DTM and how Launch’s event detection is more robust and solves this user’s problem in a transparent manner.
tbody), which contains a single table row (
tr), which contains a single table cell (
td). The hierarchy looks like this:
When an event listener is added to an element, it is either added for the “capturing phase” or the “bubbling phase”. This is very important to understand. We haven’t discussed what these phases are yet, but we will in two shakes of a lamb’s tail.
Now, let’s assume a user clicks the table cell. The event is processed through three phases, in order:
- Capturing phase: In this phase, all listeners registered for the capturing phase on the document are executed, then all listeners registered for the capturing phase on the body, then all listeners registered for the capturing phase on the table, then all listeners registered for the capturing phase on the table body, and then all listeners registered for the capturing phase on the table row.
- Target phase: In this phase, all listeners registered on the table cell are executed, regardless of whether they were registered for the capturing phase or bubbling phase.
- Bubbling phase: In this phase, all listeners registered for the bubbling phase on the table row are executed, then all listeners registered for the bubbling phase on the table body, then all listeners registered for the bubbling phase on the table, then all listeners registered for the bubbling phase on the body, and then all listeners registered for the bubbling phase on the document.
A picture speaks a thousand words, so they say:
Limitations In DTM
Here’s the kicker. What we’ve described above is how it typically functions in “modern browsers”. Notably, Internet Explorer 8 and below do not support the capturing phase and DTM was designed to work with Internet Explorer 8 (and even earlier browsers before their support was subsequently dropped). Because of this, here’s what DTM had to work with:
In order to detect click events, DTM adds an event listener to the document:
By adding a single listener to document, DTM can detect a click on any element. As DTM detects click events, it can determine which element the user clicked and whether the click is supposed to fire any DTM rules. Under normal circumstances, this works great. However…
When a click event listener is executed by the browser, it is passed an
event object. Among other things, this
event object has a method on it called
stopPropagation(). When called, it prevents the browser from continuing to “propagate” the event, or in other words, continuing processing event handlers on subsequent elements in the capturing→target→bubbling process. In our example, the DTM user’s application had added an event listener to the table cell element and in the listener function had called
event.stopPropagation(). It had the following effect:
Because the application stops propagation of the event, event listeners on the table row, table body, table, body, and document are never executed. DTM never even hears about the event. As a result, rules that should have been run are not, leading to confusion and frustration for the DTM user.
As a workaround, DTM provides a checkbox that allows the user to apply the event listener directly to the element:
With this checkbox checked in our example, DTM will add an additional event listener directly to the table cell:
By doing so, DTM now has a chance to be notified about the click event even though the application’s listener prevents propagation of the event to subsequent elements in the hierarchy.
While this approach may (and did) fix this user’s particular problem, it has some notable repercussions:
- Additional event listeners must to be added to specific elements, leading to additional processing.
- DTM must continually poll the DOM, searching for newly added elements that relate to rules where this checkbox has been checked. When new elements are found, it must add an event listener to each one.
If not careful, this can be a significant hit to site performance. It’s also not very bulletproof. For example, while we’ve talked about
event.stopPropagation(), there’s also
event.stopImmediatePropagation(), which wreaks even more havoc for DTM.
A Better Approach With Launch
With Launch, the time had come to move forward. Support for Internet Explorer 8 was dropped and with that we now have a capturing phase to work with. Instead of being one of the last to hear about an event, Launch could now be one of the first. We now add the event listener to the document on the capturing phase:
With the listener in place on the capturing phase, it no longer matters if the application stops propagation of the event while the event is on the target phase. By that time, Launch will have already been notified of the event and will have run respective rules.
You’ll notice that Launch, unlike DTM, does not have an “apply event handler directly to element” checkbox. Fortunately, you should no longer need it. We hope this improved approach prevents this frustration users have encountered at times with DTM.