The Issue

A recent client website that we built and launched also included our Customer Data Platform team performing a full Tealium TiQ implementation. The immediate goal for this implementation was for analytics purposes for their Google Analytics 4 account with the long-term goal to support AudienceStream use cases by creating a solid data-layer foundation.

Our client’s ecommerce website lived across two platforms. We utilized Joomla for their CMS and UltraCart for their ecommerce platform. Our goal was to track the customer’s journey across both platforms and capture their cart contents. This objective presented several unique challenges during the implementation phase. I will detail these challenges and how we arrived at our final solution.

The Hurdles

The portion of the site that presented the most difficult hurdles was within their ecommerce platform, UltraCart. UltraCart’s checkout theme was powered by the templating language, Velocity. The team was able to leverage their StoreFront templates and their StoreFront Object which contains cart data to populate the Data Layer. Unfortunately, this data was static and would not update until page refresh. We were required to capture changes to the cart contents, like when a user added or removed a product to their cart.

With the cart being manipulated through JavaScript, we needed a way to tap into those events. The first course of action was to dive into the UltraCart documentation to see what was available. This left a lot to the imagination. With that dead end, I turned to my browser Developer Tools. To my surprise, there were several cart event listeners that we could easily leverage. In particular, the cart:updated event look particularly promising.

tealium ultracart 1

Expanding upon the event listener, I was able to see where cart:updated was being called and which parameters it supported via the Source tab.

tealium ultracart 2

Through console logs, I was able to see the contents for both parameters. The c parameter contained the updated cart data which is exactly what we needed! While this discovery pushed us closer to our end goal, it presented new challenges. This event continued to fire multiple times for a single update to the cart. We wanted a way to reduce the event bloat and only fire a singular event. In addition, this did not provide any insight into what event type occurred within the cart. The event covered all scenarios including when a product was added or removed. We had distinct requirements for the events on adding and removing and needed a way to differentiate.

Presented with this challenge, we reached out to UltraCart support to see if there was anything available to us outside of the event listeners we found. To our surprise, support provided us with what were previously undocumented events for when a product was added or removed.

tealium ultracart code

The duplicate events were still present, requiring our solution to deduplicate events.

The Solution

There were two data sources we could leverage to dedupe events: the Data Layer within the Velocity template and the function’s c parameter with the latest cart data. The Data Layer served as the source of truth as it contained the cart’s contents upon initial page load. When an event would fire, we could compare the function’s data to the Data Layer data.

There were three pieces of data used for comparison: product ID, product price and product quantity. The product ID was preferred over the product name as the client had identical products names but with different product IDs. This would reduce any inaccurate data. The product’s price could change depending on the quantity, with quantity discount-based pricing. Lastly the product quantity could be compared, and we could determine if the change indicated an increase or decrease. These three pieces of data were distinct enough to provide us insight whether the cart contents were in fact altered. Below is the code snippet where we built out the latest product arrays:

The Boolean sameUtag would determine if an event would fire. Below is a simple function for comparing the Data Layer to the arrays we created above.

When comparing the product arrays, if there were differences in the data, we would fire an event and save that latest data to the Data Layer. This would serve as the latest reference so if there were additional changes– we would have the most up-to-date data. If the user would refresh the page, these changes would not be lost as the Velocity template was capturing the cart data.


With this logic in place, we jumped into the testing portion. Utilizing the Universal Tag Debugger custom tool within the Tealium Tools chrome extension, I was able to see the deduped events come through.

Project Learnings

With third party code, we needed a way to hook into their existing functionality to properly track the cart contents. When documentation did not provide us an immediate solution, our team explored different avenues to reach a final solution. Ultimately, the decision to reach out to support was worth it, as we were supplied with the events we needed and reduced our overall development effort. Ultimately, we did create a custom solution that turned out to be more complex than what we initially thought, due to the limitations of the technology at hand – something we often run into when augmenting existing client tech stacks. With accurate tracking in place, our client will benefit from cleaner analytics data for their reporting purposes, better user experience using the online store, and l costly overages by avoiding event bloat altogether.