MutationObserver can allow you to obtain any information about DOM changes. The word "mutation" is a synonym for "change". You can understand exactly what type of changes took place: the tag attribute change (note that MutationObserver save the old value), new or gone DOM element. You can “follow” a particular element or its “children”.
On the one hand it seems great that you can track something. But this is not the case. It’s easy to get confused what caused the change because MutationObserver tracks ALL of the changes. This is due to the fact that any change can cause MutationObserver to start tracking. Furthermore, if you want to minimize the amount of unnecessary information that it being tracked you would have to choose elements for tacking by MutationObserver more cautiously.
Thus if you want to catch a particular action you need to:
- target more precisely (not the whole document but a specific tag or the closest parent)
- “launch” MutationObserver as late as possible (in other words as close to the action you are tracking) so it won’t track the changes that are not connected to the action you are tracking.
For instance, if we are tracking sending of a form and the appearance of a message after that, we should launch MutationObserver on the tag that contains this message after clicking “Send”.
Mutation Observers have their own constructor that accepts a callback function. Once instantiated, the MutationObserver instance's observe() method can be invoked a specific element, or on the entire document.
In this guide we will listen to two kinds of changes (mutations), for two kind of use cases, which are:
- Node Insertion
- CSS Style Change
The use case 1 i.e. node insertion is when a new <span class=”error”> is inserted in the DOM into a DIV on the page. This comes in picture when your form inserts a new span element into the DOM upon an error. The moment it hears there is an error message, the script will review if the inserted node is actually an error message, and once it confirms, it pushes a dataLayer event with the content of the SPAN (the actual message).
Let’s look at the example source code of a page:
Looking at the above code you can see there is an empty DIV (#contents), this empty DIV is later appended with a new SPAN created by the function called addHTML(). And thus waits for a click event to happen on a link in the page.
In addition to the above, the next step you will follow is to create the listener. This is where you will use the MutationObserver to listen for any node which is injected into the observed target. When a node is inserted, a dataLayer push is done with a new GTM event along with the text content (message) of the SPAN.
Use case 2: In this case we will look at how to handle the form error message. These error messages are hidden until incorrect value is entered in the form filed by a user. Here we will have a hidden SPAN with the error content (message), which is then exposed when the form validation fails. Let’s have a look at the HTML:
We have a simple SPAN within a DIV with the error message in the above HTML code. Initially it is set to display: none, but the moment the link is clicked, the display status is changed to display: block
Now let’s have a look at the custom HTML tag.
In the custom HTML tag, we are not listening to the DIV; instead we are listening to the actual node or specific note which will be the target of the style change. This is really very important, and says that we should know exactly what the target will be when creating this script.
Then, you need to specify in the observer itself what was the style change. Like in the above example we simply used a change from display:none to display:block.You will observe a performance boost here because we are just listening to one single node. This is a great way of doing it in an efficient way.