How to extend

Bestehendes Tracking-Event ableiten

Um ein Tracking-Event zu erweitern oder abzuleiten kann sich am Google Tracking selbst orientiert werden. Das Tracking Google Analytics Modul baut auf Tracking Base auf und erweitert die Event-Datenrückgabe.

Implementierung und Registrierung Event

<?php
/**
 * Copyright (c) 2022 TechDivision GmbH
 * All rights reserved
 *
 * This product includes proprietary software developed at TechDivision GmbH, Germany
 * For more information see https://www.techdivision.com/
 *
 * To obtain a valid license for using this software please contact us at
 * license@techdivision.com
 */
declare(strict_types=1);

namespace TechDivision\TrackingGoogleAnalytics\Model\Events;

use Magento\Framework\Exception\NoSuchEntityException;
use TechDivision\TrackingBase\Api\GetCurrencyOfCurrentStoreServiceInterface;
use TechDivision\TrackingBase\Api\ModuleVersionDataProviderInterface;
use TechDivision\TrackingBase\Api\TrackingEventInterface;
use TechDivision\TrackingBase\Model\Services\QuoteTrackDataService;
use TechDivision\TrackingGoogleAnalytics\Model\Config;
use TechDivision\TrackingGoogleAnalytics\Model\Events\Helper\CartItemsArrayProvider;
use TechDivision\TrackingGoogleAnalytics\Model\Services\CartTrackDataService;
use TechDivision\TrackingGoogleAnalytics\Model\Snippets\GoogleTrackingSnippet;
use TechDivision\TrackingGoogleAnalytics\Model\Snippets\GoogleTrackingSnippetInterface;

/**
 * @copyright Copyright (c) 2022 TechDivision GmbH (https://www.techdivision.com)
 * @site      https://www.techdivision.com/
 * @author    MET <met@techdivision.com>
 */
class GoogleTrackingEventAddShipping extends GoogleTrackingSnippet implements
    TrackingEventInterface,
    GoogleTrackingSnippetInterface
{
    /** @var string */
    protected string $ga4EventType = "add_shipping_info";

    /** @var QuoteTrackDataService */
    protected QuoteTrackDataService $quoteTrackDataService;

    /** @var GetCurrencyOfCurrentStoreServiceInterface */
    protected GetCurrencyOfCurrentStoreServiceInterface $getCurrencyOfCurrentStoreService;

    /** @var CartItemsArrayProvider */
    protected CartItemsArrayProvider $provider;

    /** @var CartTrackDataService */
    protected CartTrackDataService $cartTrackDataService;

    /**
     * @param Config $config
     * @param ModuleVersionDataProviderInterface $moduleVersionDataProvider
     * @param QuoteTrackDataService $quoteTrackDataService
     * @param GetCurrencyOfCurrentStoreServiceInterface $getCurrencyOfCurrentStoreService
     * @param CartItemsArrayProvider $provider
     * @param CartTrackDataService $cartTrackDataService
     */
    public function __construct(
        Config $config,
        ModuleVersionDataProviderInterface $moduleVersionDataProvider,
        QuoteTrackDataService $quoteTrackDataService,
        GetCurrencyOfCurrentStoreServiceInterface $getCurrencyOfCurrentStoreService,
        CartItemsArrayProvider $provider,
        CartTrackDataService $cartTrackDataService
    ) {
        parent::__construct($config, $moduleVersionDataProvider);
        $this->quoteTrackDataService = $quoteTrackDataService;
        $this->getCurrencyOfCurrentStoreService = $getCurrencyOfCurrentStoreService;
        $this->provider = $provider;
        $this->cartTrackDataService = $cartTrackDataService;
    }

    /**
     * @param string $eventType
     * @param string $data
     * @return string
     * @throws NoSuchEntityException
     */
    public function getData(string $eventType, string $data): string
    {
        $result = [];
        if ($this->isGoogleTrackingEnabled() && $eventType === $this->getEventType()) {
            $trackData = $this->resolveRequestData($data);
            $result['ga4Event'] = $this->ga4EventType;
            $result['event'] = $eventType;
            $result['data'] = $trackData;
            return json_encode(['google' => $result]);
        }
        return json_encode(['-' => $result]);
    }

    /**
     * @return string
     */
    public function getEventType(): string
    {
        return self::TRACK_EVENT_ADD_SHIP_INFO;
    }

    /**
     * @param string $data
     * @return array
     * @throws NoSuchEntityException
     */
    public function resolveRequestData(string $data): array
    {
        $result = $this->getBaseGoogleTrackingData();
        $requestData = json_decode($data);
        $cartId = $requestData->cartId ?? '';
        $quote = $this->quoteTrackDataService->getQuoteByCartId($cartId);
        if (!$quote) {
            return [];
        }
        $result = array_merge($result, ['ecommerce' => ['items' => []]]);
        $items = $this->provider->prepareTrackingItems($quote);
        $result['ecommerce']['shipping_tier'] = $quote->getShippingAddress()->getShippingMethod();
        $result['ecommerce']['items'] = $items;
        $result['ecommerce']['currency'] =
            $quote->getCurrency()->getQuoteCurrencyCode() ?? $this->getCurrencyOfCurrentStoreService->execute();
        $result['ecommerce']['value'] = $this->cartTrackDataService->getCartTotalPrice($quote);
        return $result;
    }
}
<!-- Shipping Info Event Chain -->
<type name="TechDivision\TrackingBase\Model\Events\AddShippingInfoTrackingEvent">
    <arguments>
        <argument name="eventSnippets" xsi:type="array">
            <item name="google" xsi:type="object">TechDivision\TrackingGoogleAnalytics\Model\Events\GoogleTrackingEventAddShipping</item>
        </argument>
    </arguments>
</type>

Erweiterung Response-Handling

/**
 * Copyright (c) 2022 TechDivision GmbH
 * All rights reserved
 *
 * This product includes proprietary software developed at TechDivision GmbH, Germany
 * For more information see http://www.techdivision.com/
 *
 * To obtain a valid license for using this software please contact us at
 * license@techdivision.com
 */

/**
 * @copyright  Copyright (c) 2022 TechDivision GmbH <info@techdivision.com> - TechDivision GmbH
 * @link       http://www.techdivision.com/
 * @author     MET <met@techdivision.com>
 */
define([
    'jquery',
    'mage/utils/wrapper'
], function ($, wrapper) {
    'use strict';
    return function (trackingEvent) {

        trackingEvent.handleTrackingEventData = wrapper.wrapSuper(
            trackingEvent.handleTrackingEventData,
            function (response, eventType)
            {
                this._super(response, eventType);
                if (eventType !== trackingEvent.TRACK_EVENT_ADD_PAY_INFO) {
                    return;
                }
                let eventData = JSON.parse(response);
                if (typeof eventData.google !== 'undefined' && eventData.google.event === eventType) {
                    if (eventData.google.data.ecommerce === 'undefined' || !eventData.google.data.ecommerce) {
                        return;
                    }
                    window.dataLayer.push({
                        event: eventData.google.ga4Event,
                        base: eventData.google.data.base,
                        ecommerce: eventData.google.data.ecommerce
                    });
                }
            }
        );

        return trackingEvent;
    };
});
/**
 * Copyright (c) 2022 TechDivision GmbH
 * All rights reserved
 *
 * This product includes proprietary software developed at TechDivision GmbH, Germany
 * For more information see http://www.techdivision.com/
 *
 * To obtain a valid license for using this software please contact us at
 * license@techdivision.com
 */

/**
 * @copyright  Copyright (c) 2022 TechDivision GmbH <info@techdivision.com> - TechDivision GmbH
 * @link       http://www.techdivision.com/
 * @author     MET <met@techdivision.com>
 */
var config = {
    "config": {
        "mixins": {
            // register response handling for google tracking
            "TechDivision_TrackingBase/js/model/tracking-event": {
                "TechDivision_TrackingGoogleAnalytics/js/add-shipping-tracking-event-mixin": true
                ...
            }
        }
    }
};

Neues Tracking-Event erstellen

Grundsätzlich ist es möglich, eigene Tracking-Events zu erstellen. Die folgenden Schritte werden dafür benötigt:

Integration bzw. Anmeldung eines "Triggers"

Es muss (vermutlich) frontend-seitig ein Auslöser für ein Tracking-Event implementiert werden. Als Beispiel kann hier die Grundlogik des Tracking-Base-Moduls zurate gezogen werden.

<?php
/**
 * Copyright (c) 2023 TechDivision GmbH
 * All rights reserved
 *
 * This product includes proprietary software developed at TechDivision GmbH, Germany
 * For more information see https://www.techdivision.com/
 *
 * To obtain a valid license for using this software please contact us at
 * license@techdivision.com
 */

use Magento\Backend\Block\Template;
use Magento\Framework\View\Helper\SecureHtmlRenderer;
use TechDivision\TrackingBase\ViewModel\EventTrigger;
use Magento\Framework\Escaper;

/**
 * @copyright Copyright (c) 2023 TechDivision GmbH (https://www.techdivision.com)
 * @site      https://www.techdivision.com/
 * @author    MET <met@techdivision.com>
 */
/** @var SecureHtmlRenderer $secureRenderer */
/** @var Escaper $escaper  */
/** @var Template $block */
/** @var EventTrigger $viewModel */
$viewModel = $block->getData('event_view_model');
$scriptString = '';

if ($viewModel->getEvent() === YourVendor\YourModule\Api\YourEventInterface::YOUR_EVENT) {
    $productId = $viewModel->getProductId();
    $scriptString = <<<script
        require([
            'TechDivision_TrackingBase/js/model/tracking-event',
            'jquery',
            '!domReady'
        ], function(trackingEvent, $) {
            $(window).on('load', function() {
                setTimeout(function() {
                    <<your-awesome-delegate>>
                }, 500);
            });
        });
    script;
}

if ($viewModel->isTrackingEnabled()) {
    //phpcs:disable
    echo /* @noEscape */ $secureRenderer->renderTag('script', [], $scriptString, false);
    //phpcs:enable
}

JavaScript Mixin erstellen und einbinden

Das Tracking wird über JavaScript ausgelöst und somit wird zuerst ein Einstieg bei einem Event benötigt. Alternativ kann auch die individuelle JavaScript-Logik erweitert werden. Wir empfehlen via JS-Mixin die Logik für das Auslösen des Events zu erstellen.

define([
    'jquery',
    'mage/utils/wrapper'
], function ($, wrapper) {
    'use strict';
    return function (trackingEvent) {
        trackingEvent.handleTrackingEventData = wrapper.wrapSuper(
            trackingEvent.handleTrackingEventData,
            function (response, eventType)
            {
                this._super(response, eventType);
                if (eventType !== '<your-tracking-event-name>') {
                    return;
                }
                let eventData = JSON.parse(response);
                if (typeof eventData.google !== 'undefined' && eventData.google.event === eventType) {
                    window.dataLayer.push({
                        // your event body
                    });
                }
            }
        );
        return trackingEvent;
    };
});
var config = {
    "config": {
        "mixins": {
            // register response handling for google tracking
            "TechDivision_TrackingBase/js/model/tracking-event": {
                "YourVendor_YourModule/js/your-event-mixin": true
            }
        }
    }
};

Bei Problemen, den Code mit den bereits bestehenden Standard-Mixins vergleichen unter vendor/techdivision/tracking-google-analytics-4/view/frontend/web/js/.

Webapi für neues Event bereitstellen

In einem projektspezifischen Modul unter etc/webapi.xml einen neuen Webapi Endpunkt definieren.

<route url="/V1/td-tracking/yourEvent" method="POST">
    <service class="<your-vendor>\<your-module>\Model\Events\YourEvent" method="getData"/>
    <resources>
        <resource ref="anonymous"/>
    </resources>
</route>

Unter Model/Events ein neues Event definieren z.B.: YourEvent.php

<?php

declare(strict_types=1);

namespace YourVendor\YourModule\Model\Events;

class YourEvent extends TrackingEventChain
{
}

Für dieses Event einen Typen erstellen. Für “eventType” entweder eine Konstante mit Interface verwenden, oder einen String reinschreiben.

<type name="YourVendor\YourModule\Model\Events\YourEvent">
    <arguments>
	     <argument name="eventType" xsi:type="const">YourVendor\YourModule\Api\YourEventInterface::YOUR_EVENT</argument>
       <argument name="eventSnippets" xsi:type="array">
           <item name="google" xsi:type="object">YourVendor\YourModule\Model\Events\YourGoogleEvent</item>
       </argument>
    </arguments>
</type>

Implementierung Tracking-Event

<?php
declare(strict_types=1);

namespace YourVendor\YourModule\Model\Events;

use TechDivision\TrackingBase\Api\TrackingEventInterface;
use TechDivision\TrackingGoogleAnalytics\Model\Config;
use TechDivision\TrackingGoogleAnalytics\Model\Snippets\GoogleTrackingSnippet;
use TechDivision\TrackingGoogleAnalytics\Model\Snippets\GoogleTrackingSnippetInterface;

class YourEvent extends GoogleTrackingSnippet implements
    TrackingEventInterface,
    GoogleTrackingSnippetInterface
{
    public function getData(string $eventType, string $data): string
    {
        $result = [];
        if ($this->isGoogleTrackingEnabled() && $eventType === $this->getEventType()) {
            $trackData = $this->resolveRequestData($data);
            $result['ga4Event'] = $this->ga4EventType;
            $result['event'] = $eventType;
            $result['data'] = $trackData;
            return json_encode(['google' => $result]);
        }
        return json_encode(['-' => $result]);
    }

    public function getEventType(): string
    {
        return '';
    }

    public function resolveRequestData(string $data): array
    {
        $requestData = json_decode($data);
        //do something with the $requestData
        return ['someResult'];
    }
}