# Adding Google Tag Manager

**Because the LokiCheckout uses a JavaScript implemementation that is hugely different from other checkouts, JavaScript integrations like one with Google Tag Manager need to be recreated. This document describes the possible implementation details for Google Tag Manager in the Loki Checkout.**

The following GA4 events (and others) are possible:

- `begin_checkout`
- `add_shipping_info`
- `add_payment_info`
- `purchase`
- `view_item_list`
- `view_cart`

> Note that the [Yireo GoogleTagManager](https://github.com/yireo/Yireo_GoogleTagManager2) is completely open source and free. And it has a working integration with the LokiCheckout in the form of [https://github.com/yireo/Yireo_GoogleTagManager2LokiCheckout](https://github.com/yireo/Yireo_GoogleTagManager2LokiCheckout) Instead of spending time and money on commercial GTM extensions, you might want to consider using this community alternative and add contributions where possible.

## Data sources
When integrating GTM into the LokiCheckout, you need to be aware of the fact that the actual quote data lives on the Magento server, while the JavaScript data is just a reflection of it. How the JavaScript side is updated with the right data, is depending on things. Common data sources here are:

- `window.checkoutConfig` - a static configuration which should only be used for reading. Note that the Loki Checkout rarely depends on this, because all Loki Components directly read from the server at rendering time;
- Private data that is synced between the AJAX endpoint `/customer/section/load` and localStorage;
- Alpine.js components (Loki Components) that retrieve new data from AJAX;
- Custom AJAX calls;

## A simple event
The first event `begin_checkout` is easiest to deal with. Once the Loki Checkout page is loaded, the checkout begins:
```js
(function() {
	// trigger begin_checkout
})();
```

The GA4 `begin_checkout` event requires some data - currency, value, coupon, items - so the next question is how to retrieve data.

## Private data from localStorage or AJAX
For this, the LokiCheckout has added its own private data section `loki-checkout` to the AJAX endpoint `/customer/section/load` which is automatically synced to localStorage. Access to this private data is streamlined with an Alpine.js store `LokiLocalStorage` which makes all data within that store reactive. If you build your own Alpine.js component, properties retrieved from the Alpine.store store automatically become reactive properties in your component as well. If you are not building your own component, you need to make your JavaScript code reactive by wrapping it within `Alpine.effect(() => {}`:

```js
document.addEventListener('alpine:init', () => {
	Alpine.effect(() => {
		const lokiCheckoutSection = Alpine.store('LokiLocalStorage').get('loki-checkout');
		console.log('lokiCheckoutSection', lokiCheckoutSection);
		// trigger begin_checkout
	});
});
```

> Do not assume the local storage are there once the page loads, because it might have been cleared. Instead, use the reactive way explained above.

> Note that the `console.log()` of this example will be triggered multiple times, because localStorage might be updated frequently. If you want events to trigger only once, make sure to keep track of your events somewhere.

## Retrieving fresh cart section data
The data in the `LokiLocalStorage` store is kept up-to-date during component updates via a special Loki Component with block name `loki-checkout.utils.private-data`. This component is a target of any other component, meaning that any component update will trigger a refresh of this component as well. Once this specific component refreshes, it copies its own data (the same as retrieved via an AJAX call) towards local storage.

In short, the localStorage section `loki-checkout` is kept up-to-date at all times!

If there are no component updates, in a regular situation, the local storage will also be up-to-date as well, unless some third party script makes its own AJAX calls. In that case, if you want to refresh the data manually (by making a new AJAX call) you can do this as follows:

```js
document.addEventListener('alpine:init', () => {
	Alpine.store('LokiLocalStorage').refresh('loki-checkout');
});
```

## The `purchase` event
We recommend the `purchase` event to be triggered on the success-page, which places it outside of the scope of the LokiCheckout.
