Description
Tag Management Systems (TMS) are used by most customers to add additional tags to the storefront. These tags are added for integration to other systems, such as search or social crawlers, analytic solutions, merchandising systems, etc. Using a TMS will bring agility to the application lifecycle, as changes can be applied without going through a development cycle.
Spartacus likes to support various TMS vendor solutions. The most popular tag manager out there seems to be GTM, but we do not want to limit the architecture (and perhaps implementation) to GTM only. Moreover, CDS is also relying on a similar concept and we should try to align the design and implementation as much as possible.
TMS solutions can be integrated by a so-called data layer. There's not a data layer standard, but the core principles are the same: the application pushes data to a central JavaScript Object.
While we're not too deep (yet) into all the details of the tag managers, it's clear that Google Tag Manager (GTM) supports a flat dataLayer
array on the window object, where as Adobe Launch is driven by a more complex JavaScript Object called digitalData
on the window object. Both solution do not seem to offer an API, hence we're forced to use those global JSOs.
Besides GTM an Adobe Launch, we also like to support CDS.
High-level architecture
The high-level architecture for integrating Spartacus with several tag managers is shown in the diagram below. The example depicts an integration with GTM, but other tag mangers can be integrated in a similar way.
Event Service
The ngrx actions are a great source for the event system. We've started implementing the EventService for some of the Cart components. This resulted in the idea of a generic Event system in Spartacus where you can easily observe events.
In order to decouple from the existing ngrx actions, we like to map ngrx actions under the hood to public EventActions. EventActions are likely to become the standard in Spartacus, instead of the low level ngrx actions. This is mainly as we might consider in the future to sunset the ngrx implementation in Spartacus.
While there are a great number of (ngrx) actions available in the Store, the actions are mainly driven by data integration from the backend. There are multiple other events that could be taken into account as well, such as router events, scrolling events, Mouse Interaction, etc. While we can start with a straightforward mvp to map the existing store actions, the design should not be limited to a single source of events. Multiple EventServices could be used (we could use a multi EventService
Injection token).
We might want consider on an event payload. The event payload could keep some (meta) data for the event. This can be very useful and efficient for the event system, so that the event subscribers doesn't need to collect all data from scratch.
Datalayer Service
The DatalayerService
will subscribe to the event service and map events to the datalayer object. Whenever additional data is required, the DatalayerService
could collect this from various APIs. However, this APIs should be loosely coupled, so that services will not be added to the bundle size if they're only used by the data layer.
Activity
tobi-or-not-tobi commentedon Oct 23, 2019
Updated diagram with various tag manager solutions:
Platonn commentedon Feb 6, 2020
I can see that we'd like to avoid using facades in data collectors, right?
Then I can see at least one usecase where possibly would need to move some logic from facades to back into selectors (which we initially wanted to avoid to keep selectors simple). Maybe there are other options - needs investigation.
Let's say we want to know in the DataCollector if the active cart is stable. We can take this information from
ActiveCartService.getLoaded
(which will be renamed to.isStable()
in #6430).Knowing if the active cart is stable needs knowing:
ActiveCartService
isStable
ngrx selectorisStable
ngrx selectorAnd now calculating the
ActiveCartService.isStable
is distributed into 3 steps:isStable
selector,MultiCartService.isStable
(debouncing) andActiveCartService.getLoaded
[to be renamed toisStable
soon] (debouncing active cart id). See the implementation for more details.Platonn commentedon Feb 12, 2020
Conclusion after discussion:
Not to couple collectors with the ngrx state directly, collectors should use facades.
Platonn commentedon Feb 12, 2020
related to #5182
8 remaining items