diff --git a/Application/Extend/ViewConfig.php b/Application/Extend/ViewConfig.php old mode 100644 new mode 100755 index f9cb0f7..15b2ecd --- a/Application/Extend/ViewConfig.php +++ b/Application/Extend/ViewConfig.php @@ -25,46 +25,74 @@ class ViewConfig extends ViewConfig_parent // Google Tag Manager Container ID private $sContainerId = null; + public function getGtmContainerId() { - if ( $this->sContainerId === null ) { + if ($this->sContainerId === null) + { $this->sContainerId = ContainerFactory::getInstance() - ->getContainer() - ->get(ModuleSettingBridgeInterface::class) - ->get('vt_gtm_containerid', 'vt-gtm'); + ->getContainer() + ->get(ModuleSettingBridgeInterface::class) + ->get('vt_gtm_sContainerID', 'vt-gtm'); } return $this->sContainerId; } + private $blGA4enabled = null; + public function isGA4enabled() + { + if ($this->blGA4enabled === null) + { + $this->sContainerId = ContainerFactory::getInstance() + ->getContainer() + ->get(ModuleSettingBridgeInterface::class) + ->get('vt_gtm_blEnableGA4', 'vt-gtm'); + } + + return $this->blGA4enabled; + } public function getGtmDataLayer() { - if( !$this->getGtmContainerId() ) return "[]"; + if (!$this->getGtmContainerId()) return "[]"; $oConfig = Registry::getConfig(); - $oView = $oConfig->getTopActiveView(); /** @var FrontendController $oShop */ + $oView = $oConfig->getTopActiveView(); + /** @var FrontendController $oShop */ //$oShop = oxRegistry::getConfig()->getActiveShop(); /** @var oxShop $oShop */ $oUser = $oConfig->getUser(); - $dataLayer = [ - 'page_title' => $oView->getTitle(), - 'controller' => $this->getTopActionClassName(), - 'user' => ( $oUser ? "true" : "false" ) + $cl = $this->getTopActionClassName(); + $aPageTypes = [ + "content" => "cms", + "details" => "product", + "alist" => "listing", + "search" => "listing", + "basket" => "checkout", + "user" => "checkout", + "payment" => "checkout", + "order" => "checkout", + "thankyou" => "checkout", ]; - return json_encode([$dataLayer],JSON_PRETTY_PRINT); + $dataLayer = [ + 'page' => [ + 'type' => $aPageTypes[$cl] ?? "unknown", + 'title' => $oView->getTitle(), + 'cl' => $cl, + ], + 'userid' => ($oUser ? $oUser->getId() : false), + 'sessionid' => session_id() ?? false, + //'httpref' => $_SERVER["HTTP_REFERER"] ?? "unknown" + ]; + + return json_encode([$dataLayer], JSON_PRETTY_PRINT); unset($dataLayer["user"]["http"]); // das brauchen wir hier nicht - $cl = $this->getActiveClassName(); - if( $cl === "content" ) $dataLayer["page"]["type"] = "cms"; - elseif( $cl === "details" ) $dataLayer["page"]["type"] = "product"; - elseif( in_array($cl,["alist","search"]) ) $dataLayer["page"]["type"] = "listing"; - elseif( in_array($cl,["basket","user","payment","order","thankyou"]) ) $dataLayer["page"]["type"] = "checkout"; - - return json_encode([$dataLayer],JSON_PRETTY_PRINT); + return json_encode([$dataLayer], JSON_PRETTY_PRINT); /* // --- Produktdaten --- $transactionProducts = []; @@ -87,11 +115,15 @@ class ViewConfig extends ViewConfig_parent */ } - public function isPromotionList($listId) + public function triggerGA4events() { - $oConfig = Registry::getConfig(); - $aPromotionListIds = $oConfig->getConfigParam("") ?? [ 'bargainItems', 'newItems', 'topBox', 'alsoBought', 'accessories', 'cross' ]; - + // general events } + + public function isPromotionList($listId) + { + $oConfig = Registry::getConfig(); + $aPromotionListIds = $oConfig->getConfigParam("") ?? ['bargainItems', 'newItems', 'topBox', 'alsoBought', 'accessories', 'cross']; + } } \ No newline at end of file diff --git a/Application/views/admin/de/module_options.php b/Application/views/admin/de/module_options.php old mode 100644 new mode 100755 index bb0a054..dffc84e --- a/Application/views/admin/de/module_options.php +++ b/Application/views/admin/de/module_options.php @@ -26,6 +26,6 @@ input.confinput:hover {outline:3px solid #ff3600;} $aLang = [ 'charset' => 'UTF-8', 'SHOP_MODULE_GROUP_vt_gtm_settings' => $style . 'Einstellungen', - 'SHOP_MODULE_vt_gtm_containerid' => 'Container ID', + 'SHOP_MODULE_vt_gtm_sContainerID' => 'Container ID', 'SHOP_MODULE_vt_gtm_promotionlistids' => 'Promotion Produktlisten IDs
Weitere Infos zu dieser Einstellung: Modui-Wiki
', ]; diff --git a/Application/views/blocks/_gtm_js.tpl b/Application/views/blocks/_gtm_js.tpl old mode 100644 new mode 100755 index 46e65c2..3539472 --- a/Application/views/blocks/_gtm_js.tpl +++ b/Application/views/blocks/_gtm_js.tpl @@ -12,6 +12,7 @@ })(window, document, 'script', 'dataLayer', '[{$oViewConf->getGtmContainerId()}]'); + [{$oViewConf->triggerGA4events()}] [{if $oViewConf->getTopActionClassName() === "alist" }] [{* include file="ga4_view_item_list.tpl" gtmCategory=$oView->getActiveCategory() gtmProducts=$oView->getArticleList() listtype=$oView->getListType() *}] [{elseif $oViewConf->getTopActionClassName() === "details" }] diff --git a/Application/views/blocks/impression.tpl b/Application/views/blocks/widget_product_list.tpl similarity index 100% rename from Application/views/blocks/impression.tpl rename to Application/views/blocks/widget_product_list.tpl diff --git a/Application/views/ga4/add_payment_info.tpl b/Application/views/ga4/add_payment_info.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/add_shipping_info.tpl b/Application/views/ga4/add_shipping_info.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/begin_checkout.tpl b/Application/views/ga4/begin_checkout.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/generate_lead.tpl b/Application/views/ga4/generate_lead.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/login.tpl b/Application/views/ga4/login.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/purchase.tpl b/Application/views/ga4/purchase.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/remove_from_cart.tpl b/Application/views/ga4/remove_from_cart.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/search.tpl b/Application/views/ga4/search.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/select_content.tpl b/Application/views/ga4/select_content.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/select_item.tpl b/Application/views/ga4/select_item.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/select_promotion.tpl b/Application/views/ga4/select_promotion.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/sign_up.tpl b/Application/views/ga4/sign_up.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/view_cart.tpl b/Application/views/ga4/view_cart.tpl new file mode 100755 index 0000000..e69de29 diff --git a/Application/views/ga4/view_promotion.tpl b/Application/views/ga4/view_promotion.tpl new file mode 100755 index 0000000..e69de29 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 4d67c56..2508a71 --- a/README.md +++ b/README.md @@ -1,34 +1,23 @@ # [vt] Google Tag Manager Google Tag Manager integration for OXID eShop v6.2 und höher -module version 0.2.0 ( 2018-12-04 ) +module version 0.5.0 ( 2021-12-10 ) -# Installation +## Installation * ``composer require vanilla-thunder/oxid-module-gtm --no-update`` - -* Inhalt von "copy_this" in den Shop hochladen * Modul aktivieren und Moduleinstellungen konfigurieren -# Tag Manager konfigurieren: +## Tag Manager konfigurieren: + https://support.google.com/tagmanager/answer/9442095 +## Google Analytics 4 Einrichtung +## GA4 Events / Customizing +für alle implementierten GA4 Events existieren Templates unter `source/modules/GoogleTagManager/Application/views/ga4/`, dabei entspricht der Dateiname dem Eventnamen in GA4. +Die Einbindung dieser Event-Templates erfolgt über TPL-Blöcke unter `source/modules/GoogleTagManager/Application/views/blocks/`. +## Universal Analytics Events - -Alle drei unterstützten Tag Manager werden mit Daten aus einer gemeinsamen Datenschicht (dataLayer) gefüttert. -Für die einfachste Übersicht der enthaltenen Daten empfehle ich den Vorschau-Modus vom Google Tag Manager. - -Bei jedem Seitenaufruf wird die Datenschicht mit einigen wenigen Infos erstellt, die man zum reinen Erfassen der Seitenaufrufe benötigt: - + **page.type** - Seitentyp: default / cms / product / listing / checkout (an google analytics angelehnt) - + **page.title** - Seitentitel (außer Startseite, sie hat keinen Titel. Danke OXID...) - + **page.class** - OXID Controller Klasse (start, search, etc) - + **user.country** - Land des Benutzers, sofern dieser angemeldet ist. - + **user.httpref** - http referrer - -Alle für Ecommerce Tracking releavanten Daten werden mit speziellen Ecommerce Events in die Datenschicht eingefügt. -Hier ist ein Beispiel für die Einrichtung von Enhanced Ecomemrce Tracking über Google Tag Manager: - -**"EE-Trigger" für Ecomemrce-Tags (Beispiel für Google Tag Manager):** +**"EE-Trigger" für Ecomemrce-Tags (Beispiel für Google Tag Manager):** + Triggertyp: Benutzerdefiniertes Ereignis + Ereignisname: ``ee\..*`` + Übereinstimmung mit regulärem Ausdruck verwenden @@ -41,16 +30,26 @@ Hier ist ein Beispiel für die Einrichtung von Enhanced Ecomemrce Tracking über + Label: {{Event Label}} + Trigger : EE-Trigger -Eine Video-Anleitung mit der kompletten Google Analytics Einrichtung folgt in Kürze. +## Verfügbare Datalayer Variablen +Für die einfachste Übersicht der enthaltenen Daten empfehle ich den Vorschau-Modus vom Google Tag Manager. + +Bei jedem Seitenaufruf wird die Datenschicht mit einigen wenigen Infos erstellt, die man zum reinen Erfassen der Seitenaufrufe benötigt: + + **page.type** - Seitentyp: default / cms / product / listing / checkout (an google analytics angelehnt) + + **page.title** - Seitentitel (außer Startseite, sie hat keinen Titel. Danke OXID...) + + **page.cl** - OXID Controller Klasse (start, search, etc) + + **userid** - oxID vom Benutzer bzw `false` falls nicht eingeloggt + + **sessionid** - session iD + +Alle für Ecommerce Tracking releavanten Daten werden mit speziellen Ecommerce Events in die Datenschicht eingefügt. +Hier ist ein Beispiel für die Einrichtung von Enhanced Ecomemrce Tracking über Google Tag Manager: + -### Google Analytics 4 Referenz -https://developers.google.com/tag-manager/ecommerce-ga4 ### LICENSE AGREEMENT - [bla] tag-manager - Copyright (C) 2018 bestlife AG - info: oxid@bestlife.ag + [vt] google-tag-manager + Copyright (C) 2021 Marat Bedoev + info: info@mb-dev.pro oder so /** @todo: überarbeiten, wenn ich wieder nüchtern bin */ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; diff --git a/metadata.php b/metadata.php old mode 100644 new mode 100755 index 3d912a3..8dee4b4 --- a/metadata.php +++ b/metadata.php @@ -13,144 +13,155 @@ **/ $sMetadataVersion = '2.1'; -$aModule = [ - 'id' => 'vt-gtm', - 'title' => '[vt] Google Tag Manager', +$aModule = [ + 'id' => 'vt-gtm', + 'title' => '[vt] Google Tag Manager', 'description' => 'Google Tag Manager Integration for OXID eShop v6.2+', - 'thumbnail' => 'thumbnail.png', - 'version' => '0.5.0 ( 2021-07-17 )', - 'author' => 'Marat Bedoev', - 'email' => openssl_decrypt("Az6pE7kPbtnTzjHlPhPCa4ktJLphZ/w9gKgo5vA//p4=", str_rot13("nrf-128-pop"), str_rot13("gvalzpr")), - 'url' => 'https://github.com/vanilla-thunder/oxid-module-gtm', - 'extend' => [ + 'thumbnail' => 'thumbnail.png', + 'version' => '0.5.0 ( 2021-07-17 )', + 'author' => 'Marat Bedoev', + 'email' => openssl_decrypt("Az6pE7kPbtnTzjHlPhPCa4ktJLphZ/w9gKgo5vA//p4=", str_rot13("nrf-128-pop"), str_rot13("gvalzpr")), + 'url' => 'https://github.com/vanilla-thunder/oxid-module-gtm', + 'extend' => [ \OxidEsales\Eshop\Core\ViewConfig::class => VanillaThunder\GoogleTagManager\Application\Extend\ViewConfig::class ], - 'templates' => [ - // separate ee-event templates for easy integration - //'ga4_add_to_cart.tpl' => 'vt/GoogleTagManager/Application/views/ga4/add_to_cart.tpl', - //'ga4_view_item.tpl' => 'vt/GoogleTagManager/Application/views/ga4/view_item.tpl', - //'ga4_view_item_list.tpl' => 'vt/GoogleTagManager/Application/views/ga4/view_item_list.tpl', - 'gtm_ua_impression' => 'vt/GoogleTagManager/Application/views/ua/impression.tpl' + 'templates' => [ + // GA4 events + 'ga4_add_payment_info.tpl' => 'vt/GoogleTagManager/Application/views/ga4/add_payment_info.tpl', + 'add_shipping_info.tpl' => 'vt/GoogleTagManager/Application/views/ga4/add_shipping_info.tpl', + 'ga4_add_to_cart.tpl' => 'vt/GoogleTagManager/Application/views/ga4/add_to_cart.tpl', + 'ga4_begin_checkout.tpl' => 'vt/GoogleTagManager/Application/views/ga4/begin_checkout.tpl', + 'ga4_generate_lead.tpl' => 'vt/GoogleTagManager/Application/views/ga4/generate_lead.tpl', + 'ga4_login.tpl' => 'vt/GoogleTagManager/Application/views/ga4/login.tpl', + 'ga4_purchase.tpl' => 'vt/GoogleTagManager/Application/views/ga4/purchase.tpl', + 'ga4_remove_from_cart.tpl' => 'vt/GoogleTagManager/Application/views/ga4/remove_from_cart.tpl', + 'ga4_search.tpl' => 'vt/GoogleTagManager/Application/views/ga4/search.tpl', + 'ga4_select_content.tpl' => 'vt/GoogleTagManager/Application/views/ga4/select_content.tpl', + 'ga4_select_item.tpl' => 'vt/GoogleTagManager/Application/views/ga4/select_item.tpl', + 'ga4_select_promotion.tpl' => 'vt/GoogleTagManager/Application/views/ga4/select_promotion.tpl', + 'ga4_sign_up.tpl' => 'vt/GoogleTagManager/Application/views/ga4/sign_up.tpl', + 'ga4_view_cart.tpl' => 'vt/GoogleTagManager/Application/views/ga4/view_cart.tpl', + 'ga4_view_item.tpl' => 'vt/GoogleTagManager/Application/views/ga4/view_item.tpl', + 'ga4_view_item_list.tpl' => 'vt/GoogleTagManager/Application/views/ga4/view_item_list.tpl', + 'ga4_view_promotion.tpl' => 'vt/GoogleTagManager/Application/views/ga4/view_promotion.tpl', /* - + 'gtm_ua_impression' => 'vt/GoogleTagManager/Application/views/ua/impression.tpl' 'gtm_view_promotion.tpl' => 'vt/GoogleTagManager/Application/views/view_promotion.tpl', 'gtm_select_promotion.tpl' => 'vt/GoogleTagManager/Application/views/select_promotion.tpl', 'gtm_begin_checkout.tpl' => 'vt/GoogleTagManager/Application/views/begin_checkout.tpl', */ ], - 'blocks' => [ + 'blocks' => [ // tag manager js [ 'template' => 'layout/base.tpl', - 'block' => 'head_meta_robots', - 'file' => '/Application/views/blocks/_gtm_js.tpl' + 'block' => 'head_meta_robots', + 'file' => '/Application/views/blocks/_gtm_js.tpl' ], // tag manager nojs [ 'template' => 'layout/base.tpl', - 'block' => 'theme_svg_icons', - 'file' => '/Application/views/blocks/_gtm_nojs.tpl' + 'block' => 'theme_svg_icons', + 'file' => '/Application/views/blocks/_gtm_nojs.tpl' ], // add to cart [ 'template' => 'layout/header.tpl', - 'block' => 'header_main', - 'file' => '/Application/views/blocks/add_to_cart.tpl' + 'block' => 'header_main', + 'file' => '/Application/views/blocks/add_to_cart.tpl' ], - // impressions + // widget_product_list [ - 'template' => 'widget/product/listitem_grid.tpl', - 'block' => 'widget_product_listitem_grid', - 'file' => '/Application/views/blocks/impression.tpl' - ], - [ - 'template' => 'widget/product/listitem_infogrid.tpl', - 'block' => 'widget_product_listitem_infogrid', - 'file' => '/Application/views/blocks/impression.tpl' - ], - [ - 'template' => 'widget/product/listitem_line.tpl', - 'block' => 'widget_product_listitem_line', - 'file' => '/Application/views/blocks/impression.tpl' + 'template' => 'widget/product/list.tpl', + 'block' => 'widget_product_list', + 'file' => '/Application/views/blocks/widget_product_list.tpl' ], // details [ 'template' => 'page/details/inc/productmain.tpl', - 'block' => 'details_productmain_title', - 'file' => '/Application/views/blocks/detail.tpl' + 'block' => 'details_productmain_title', + 'file' => '/Application/views/blocks/detail.tpl' ], // checkout [ 'template' => 'page/checkout/basket.tpl', - 'block' => 'checkout_basket_main', - 'file' => '/Application/views/blocks/checkout_s1.tpl' + 'block' => 'checkout_basket_main', + 'file' => '/Application/views/blocks/checkout_s1.tpl' ], [ 'template' => 'form/user_checkout_change.tpl', - 'block' => 'user_checkout_change', - 'file' => '/Application/views/blocks/checkout_s2.tpl' + 'block' => 'user_checkout_change', + 'file' => '/Application/views/blocks/checkout_s2.tpl' ], [ 'template' => 'form/user_checkout_register.tpl', - 'block' => 'user_checkout_register', - 'file' => '/Application/views/blocks/checkout_s2.tpl' + 'block' => 'user_checkout_register', + 'file' => '/Application/views/blocks/checkout_s2.tpl' ], [ 'template' => 'form/user_checkout_noregister.tpl', - 'block' => 'user_checkout_noregister', - 'file' => '/Application/views/blocks/checkout_s2.tpl' + 'block' => 'user_checkout_noregister', + 'file' => '/Application/views/blocks/checkout_s2.tpl' ], [ 'template' => 'page/checkout/payment.tpl', - 'block' => 'checkout_payment_main', - 'file' => '/Application/views/blocks/checkout_s3.tpl' + 'block' => 'checkout_payment_main', + 'file' => '/Application/views/blocks/checkout_s3.tpl' ], [ 'template' => 'page/checkout/order.tpl', - 'block' => 'checkout_order_main', - 'file' => '/Application/views/blocks/checkout_s4.tpl' + 'block' => 'checkout_order_main', + 'file' => '/Application/views/blocks/checkout_s4.tpl' ], [ 'template' => 'page/checkout/thankyou.tpl', - 'block' => 'checkout_thankyou_main', - 'file' => '/Application/views/blocks/checkout_s5.tpl' + 'block' => 'checkout_thankyou_main', + 'file' => '/Application/views/blocks/checkout_s5.tpl' ] ], - 'settings' => [ + 'settings' => [ [ - 'group' => 'vt_gtm_settings', - 'name' => 'vt_gtm_containerid', - 'type' => 'str', - 'value' => 'GTM-', + 'group' => 'vt_gtm_settings', + 'name' => 'vt_gtm_sContainerID', + 'type' => 'str', + 'value' => 'GTM-', 'position' => 0 ], [ - 'group' => 'vt_gtm_settings', - 'name' => 'vt_gtm_enable_ga4', - 'type' => 'bool', - 'value' => true, + 'group' => 'vt_gtm_settings', + 'name' => 'vt_gtm_blGA4enabled', + 'type' => 'bool', + 'value' => true, 'position' => 1 ], [ - 'group' => 'vt_gtm_settings', - 'name' => 'vt_gtm_enable_ua', - 'type' => 'bool', - 'value' => true, + 'group' => 'vt_gtm_settings', + 'name' => 'vt_gtm_blUAenabled', + 'type' => 'bool', + 'value' => true, 'position' => 2 ], [ - 'group' => 'vt_gtm_settings', - 'name' => 'vt_gtm_mpapisecret', - 'type' => 'str', - 'value' => '', + 'group' => 'vt_gtm_settings', + 'name' => 'vt_gtm_sMpapisecret', + 'type' => 'str', + 'value' => '', 'position' => 3 ], [ - 'group' => 'vt_gtm_settings', - 'name' => 'vt_gtm_promotionlistids', - 'type' => 'arr', - 'value' => [], + 'group' => 'vt_gtm_settings', + 'name' => 'vt_gtm_aPromotionlistIDs', + 'type' => 'arr', + 'value' => [], 'position' => 4 + ], + [ + 'group' => 'vt_gtm_settings', + 'name' => 'vt_gtm_blEnableDebug', + 'type' => 'bool', + 'value' => false, + 'position' => 999 ] + ] ]; \ No newline at end of file diff --git a/thumbnail.png b/thumbnail.png new file mode 100755 index 0000000..ecde9d2 Binary files /dev/null and b/thumbnail.png differ