Compare commits

..

30 Commits
0.5.0 ... 1.0

Author SHA1 Message Date
f6f4f87627 adjusted general texts of the mod 2023-01-20 11:04:22 +01:00
d9b8c274ce adjusted keywords and desc in composer.json 2023-01-20 11:04:04 +01:00
f41b2edeed adjust target-directory 2023-01-20 09:58:21 +01:00
69073c0109 adjusted desc text in metadata and paths to template files 2023-01-20 09:57:38 +01:00
b12884f99b fix namespace bug in composer.json 2023-01-20 09:38:25 +01:00
c7d8fdcf6a extend readme and metadata-desc 2023-01-20 09:33:36 +01:00
87ce3efc5f rm unnecessary files 2023-01-20 09:33:21 +01:00
f9d7f0b2e9 add missing blacklist-filter in composer.json 2023-01-19 15:36:54 +01:00
dfab91a71a adding missing standard-files; rebranding and moving ViewConfig extension 2023-01-19 15:31:56 +01:00
ed75197a64 add info to readme 2023-01-19 11:37:40 +01:00
b861aef8a9 fix bug that'd stop jquery from running duo to no-datalayer error 2023-01-19 09:32:38 +01:00
a74b6d9f15 add cookieManager switch 2023-01-17 14:42:17 +01:00
633c1336a8 fix bug that would display cat path 2023-01-17 09:57:37 +01:00
a5378ec70e adding position to detail.tpl metadata entry 2023-01-16 15:25:59 +01:00
34c27d101d commenting out debug 2023-01-12 08:38:51 +01:00
fec7bf5c13 add list mandatory params 2023-01-11 15:54:52 +01:00
2b864f41e8 cleaning + rm unnecessary " } " 2023-01-11 15:31:56 +01:00
9ae1afa326 reworking structure and add 2 missing mandatory params 2023-01-11 15:25:27 +01:00
664119f89e genuine reworking structure and aligning all 2023-01-11 15:25:02 +01:00
c83e908da1 reworking view_cart to add necessary parameters 2023-01-11 15:04:41 +01:00
95de52600d add add_to_cart 2023-01-11 14:43:13 +01:00
6b039b6c9a add view_search_result 2023-01-10 15:49:54 +01:00
1aad369e36 add view_item_list 2023-01-10 14:22:49 +01:00
76e7bd10f6 switching event names to recommendation form google 2023-01-10 09:54:34 +01:00
6bfe8b90e6 add translations + add currency 2022-12-20 11:52:25 +01:00
4c08f58777 fix typo in composer.json 2022-12-01 13:57:52 +01:00
5de90a2488 config composer.json to fit ce-metapackage 6.0 - 6.1 2022-12-01 13:53:16 +01:00
f0466493b3 rework code to actually fit 6.0.x && 6.1x 2022-12-01 13:30:09 +01:00
5b4bd5a05a add purchase.tpl content 2022-12-01 13:29:35 +01:00
ed767efa8a alter Zwiscehnstand 2022-06-09 20:41:59 +02:00
40 changed files with 764 additions and 574 deletions

13
.php-cs-fixer.php Normal file
View File

@ -0,0 +1,13 @@
<?php
$finder = PhpCsFixer\Finder::create()
->in(__DIR__)
;
$config = new PhpCsFixer\Config();
return $config->setRules([
'@PHP73Migration' => true,
'@PSR12' => true
])
->setFinder($finder)
;

View File

@ -1,5 +0,0 @@
<?php
namespace VanillaThunder\GoogleTagManager\Application\Extend;
class ViewConfig_parent extends \OxidEsales\Eshop\Core\ViewConfig {};

25
Application/views/admin/de/module_options.php Normal file → Executable file
View File

@ -17,15 +17,30 @@ $style = '<style type="text/css">
.groupExp a.rc b {font-size:medium;color:#ff3600;}
.groupExp dt .txt,
.groupExp dt .select,
.groupExp dt .txtfield {width:250px !important; margin: 2px !important; padding: 1px 4px !important; border: 1px solid #ccc !important; }
.groupExp dt .txtfield {width:250px !important; margin: 2px !important; padding: 1px 4px !important; border: 1px solid #ccc !important; }
.groupExp dt textarea.txtfield { min-height: 125px;}
.groupExp dl { display:block !important;}
input.confinput {position:fixed;top:20px;right:70px;background:#008B2D;padding:10px 25px;color:white;border:1px solid black;cursor:pointer;font-size:125%;}
input.confinput:hover {outline:3px solid #ff3600;}
</style>';
$aLang = [
'charset' => 'UTF-8',
'SHOP_MODULE_GROUP_vt_gtm_settings' => $style . 'Einstellungen',
'SHOP_MODULE_vt_gtm_containerid' => 'Container ID',
'SHOP_MODULE_vt_gtm_promotionlistids' => 'Promotion Produktlisten IDs <div>Weitere Infos zu dieser Einstellung: <b><u><a href="https://github.com/vanilla-thunder/oxid-module-gtm/wiki/Promotion-Produktlisten" target="_blank">Modui-Wiki</a></u></b></div>',
'charset' => 'UTF-8',
'SHOP_MODULE_vt_gtm_sContainerID' => 'Container ID',
'SHOP_MODULE_GROUP_vt_gtm_settings' => 'Einstellungen',
'SHOP_MODULE_vt_gtm_blGA4enab' => 'GA4 Aktivieren',
'SHOP_MODULE_vt_gtm_blUAenabled' => 'UA Aktivieren',
'SHOP_MODULE_vt_gtm_blEnableDebug' => 'Debug-Modus aktivieren',
// for cookie manager settings
'SHOP_MODULE_GROUP_vt_gtm_settings_cookiemanager' => 'Cookie Manager Einstellungen',
'SHOP_MODULE_vt_gtm_settings_hasOwnCookieManager' => 'Eigenen Cookie Manager nutzen?
<strong style="color: red">Hinweis (Fragezeichen) lesen!</strong>',
'HELP_SHOP_MODULE_vt_gtm_settings_hasOwnCookieManager' => 'Stellen Sie sicher, dass Sie ein Modul installiert haben,
dass die Methode "blAcceptedCookie" implementiert.<br> Sollten Sie sich nicht sicher sein kontaktieren Sie Ihren
technischen Ansprechpartner.<br><br>
<strong>Wichtig!</strong> Das Aktivieren dieser Checkbox kann <u>ohne dem nötigen technischen Wissen</u> den Shop-Ablauf im Frontend stören!<hr>
Die Checkbox muss nicht aktiviert werden, sofern die Cookies beispielsweise direkt via Google Cookie-Banner integriert werden.
Bei Fragen <u>kontaktieren Sie bitte</u> auch hier einen entsprechenden technischen Ansprechpartner.',
'SHOP_MODULE_vt_gtm_settings_cookieName' => 'Cookie-Name',
];

55
Application/views/blocks/_gtm_js.tpl Normal file → Executable file
View File

@ -1,24 +1,61 @@
[{if $oViewConf->getGtmContainerId()}][{strip}]
<!-- Google Tag Manager -->
<script>
var dataLayer = [{$oViewConf->getGtmDataLayer()}] || [];
(function (w, d, s, l, i) {
[{assign var="d3VtConfigObject" value=$oViewConf->getConfig()}]
[{if $d3VtConfigObject->getConfigParam('vt_gtm_settings_hasOwnCookieManager')}]
[{if $oViewConf->blAcceptedCookie($d3VtConfigObject->getConfigParam('vt_gtm_settings_cookieName'))}]
[{if $oViewConf->getGtmContainerId()}][{strip}]
<!-- Google Tag Manager -->
<script>
var dataLayer = [{$oViewConf->getGtmDataLayer()}] || [];
(function (w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', '[{$oViewConf->getGtmContainerId()}]');
})(window, document, 'script', 'dataLayer', '[{$oViewConf->getGtmContainerId()}]');
</script>
<!-- End Google Tag Manager -->
[{$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" }]
[{* include file="ga4_view_item.tpl" gtmProduct=$oView->getProduct() *}]
[{elseif $oViewConf->getTopActionClassName() === "search" }]
[{elseif $oViewConf->getTopActionClassName() === "basket" }]
[{/if}]
[{/strip}][{/if}]
[{else}]
<script>
var dataLayer = [{$oViewConf->getGtmDataLayer()}] || [];
</script>
[{/if}]
[{else}]
[{if $oViewConf->getGtmContainerId()}][{strip}]
<!-- Google Tag Manager -->
<script>
var dataLayer = [{$oViewConf->getGtmDataLayer()}] || [];
(function (w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', '[{$oViewConf->getGtmContainerId()}]');
</script>
<!-- End Google Tag Manager -->
[{$oViewConf->triggerGA4events()}]
[{if $oViewConf->getTopActionClassName() === "alist" }]
[{* include file="ga4_view_item_list.tpl" gtmCategory=$oView->getActiveCategory() gtmProducts=$oView->getArticleList() listtype=$oView->getListType() *}]
[{* include file="ga4_view_item_list.tpl" gtmCategory=$oView->getActiveCategory() gtmProducts=$oView->getArticleList() listtype=$oView->getListType() *}]
[{elseif $oViewConf->getTopActionClassName() === "details" }]
[{* include file="ga4_view_item.tpl" gtmProduct=$oView->getProduct() *}]
[{* include file="ga4_view_item.tpl" gtmProduct=$oView->getProduct() *}]
[{elseif $oViewConf->getTopActionClassName() === "search" }]
[{elseif $oViewConf->getTopActionClassName() === "basket" }]
[{/if}]
[{/strip}][{/if}]
[{/strip}][{/if}]
[{/if}]
[{$smarty.block.parent}]

View File

@ -1,57 +1,31 @@
[{strip}]
[{assign var='gtmCartArticles' value=$oView->getBasketArticles()}]
<script>
dataLayer.push({"event": null, "eventLabel": null, "ecommerce": null}); /* Clear the previous ecommerce object. */
dataLayer.push({
'event': 'ee.checkout',
'eventLabel':'Checkout Step 1',
'ecommerce': {
'checkout': {
'actionField': {'step': 1},
'products': [
[{foreach from=$oxcmp_basket->getContents() item=basketitem name=gtmCartContents key=basketindex}]
[{assign var='_price' value=$basketitem->getUnitPrice()}]
{
'id': '[{$gtmCartArticles[$basketindex]->oxarticles__oxartnum->value}]',
'name': '[{$gtmCartArticles[$basketindex]->oxarticles__oxtitle->value}]',
'variant': '[{$gtmCartArticles[$basketindex]->oxarticles__oxvarselect->value}]',
'price': [{$_price->getPrice()}],
'quantity':[{$basketitem->getAmount()}],
'position':[{$smarty.foreach.gtmCartContents.index}]
}[{if !$smarty.foreach.gtmCartContents.last}],[{/if}]
[{/foreach}]
]
}
}
});
[{*
var gtmCartContents = {[{foreach key=basketindex from=$oxcmp_basket->getContents() item=basketitem name=gtmCartContents}]
'[{$basketindex}]':{ 'id':'[{$gtmCartArticles[$basketindex]->oxarticles__oxartnum->value}]' }[{if !$smarty.foreach.gtmCartContents.last}],[{/if}][{/foreach}]
};
[{$smarty.block.parent}]
[{capture name='removeFromBasket'}]
$('#basketRemove').on('click', function() {
var _checked = [],
_products = [];
[{*$oxcmp_basket|get_class_methods|dumpvar*}]
$('input:checkbox:checked[name^="aproducts"][name*="remove"]').each(function() { _checked.push($(this).attr('name').replace('aproducts[','').replace('][remove]','')); });
if(_checked.length == 0) return;
_checked.forEach(function(_oxid) { _products.push({ 'id':gtmCartContents[_oxid].id}) });
dataLayer.push({
'event':'ee.removeFromCart',
'ecommerce': {
'currencyCode': '[{$currency->name}]',
'remove': {
'products': _products
}
}
});
});
[{/capture }]
[{oxscript add=$smarty.capture.removeFromBasket}]
*}]
</script>
[{/strip}]
[{$smarty.block.parent}]
[{assign var='gtmCartArticles' value=$oView->getBasketArticles()}]
[{strip}][{capture assign=d3_ga4_view_cart}]
dataLayer.push({"event": null, "eventLabel": null, "ecommerce": null}); /* Clear the previous ecommerce object. */
dataLayer.push({
'event': 'view_cart',
'eventLabel':'Checkout Step 1',
'ecommerce': {
'actionField': "step: 1",
'currency': "[{$currency->name}]",
'value': [{$oxcmp_basket->getBruttoSum()}],
'items': [
[{foreach from=$oxcmp_basket->getContents() item=basketitem name=gtmCartContents key=basketindex}]
[{assign var='_price' value=$basketitem->getUnitPrice()}]
{
'item_id': '[{$gtmCartArticles[$basketindex]->oxarticles__oxartnum->value}]',
'item_name': '[{$gtmCartArticles[$basketindex]->oxarticles__oxtitle->value}]',
'item_variant': '[{$gtmCartArticles[$basketindex]->oxarticles__oxvarselect->value}]',
'price': [{$_price->getPrice()}],
'quantity':[{$basketitem->getAmount()}],
'position':[{$smarty.foreach.gtmCartContents.index}]
}[{if !$smarty.foreach.gtmCartContents.last}],[{/if}]
[{/foreach}]
]
}
});
[{/capture}][{/strip}]
[{oxscript add=$d3_ga4_view_cart}]

View File

@ -1,3 +1,5 @@
[{$smarty.block.parent}]
[{strip}]
<script>
dataLayer.push({"event": null, "eventLabel": null, "ecommerce": null}); /* Clear the previous ecommerce object. */
@ -5,33 +7,29 @@
[{assign var="_gtmArticles" value=$_gtmOrder->getOrderArticles()}]
dataLayer.push({
'event': 'ee.transaction',
'event': 'purchase',
'eventLabel':'Checkout Step 5',
'ecommerce': {
'purchase': {
'actionField': {
'id':'[{$_gtmOrder->oxorder__oxordernr->value}]',
'affiliation':'[{$oxcmp_shop->oxshops__oxname->value}]',
'revenue':'[{$_gtmOrder->oxorder__oxtotalordersum->value}]',
'tax':'[{math equation="x+y" x=$_gtmOrder->oxorder__oxartvatprice1->value y=$_gtmOrder->oxorder__oxartvatprice2->value }]',
'shipping':'[{$_gtmOrder->oxorder__oxdelcost->value}]'
/*'coupon':'CANO25' //if a coupon code was used for this order*/
},
'products':[
[{foreach from=$_gtmArticles item="_gtmArticle" name="gtmArticles"}]
{
'id':'[{$_gtmArticle->oxorderarticles__oxartnum->value}]',
'name': '[{$_gtmArticle->oxorderarticles__oxtitle->value}]',
'variant':'[{$_gtmArticle->oxorderarticles__oxselvariant->value}]',
'price': [{$_gtmArticle->oxorderarticles__oxprice->value}],
'quantity':[{$_gtmArticle->oxorderarticles__oxamount->value}],
'position':[{$smarty.foreach.gtmArticles.iteration}]
}[{if !$smarty.foreach.gtmArticles.last}],[{/if}]
[{/foreach}]
]
}
'transaction_id': '[{$_gtmOrder->oxorder__oxordernr->value}]',
'affiliation': '[{$oxcmp_shop->oxshops__oxname->value}]',
'value': '[{$_gtmOrder->oxorder__oxtotalordersum->value}]',
'tax': '[{math equation="x+y" x=$_gtmOrder->oxorder__oxartvatprice1->value y=$_gtmOrder->oxorder__oxartvatprice2->value }]',
'shipping': '[{$_gtmOrder->oxorder__oxdelcost->value}]',
'currency': '[{$_gtmOrder->getFieldData('oxcurrency')}]',
'items':
[
[{foreach from=$_gtmArticles item="_gtmArticle" name="gtmArticles"}]
{
'id': '[{$_gtmArticle->oxorderarticles__oxartnum->value}]',
'name': '[{$_gtmArticle->oxorderarticles__oxtitle->value}]',
'variant': '[{$_gtmArticle->oxorderarticles__oxselvariant->value}]',
'price': [{$_gtmArticle->oxorderarticles__oxprice->value}],
'quantity': [{$_gtmArticle->oxorderarticles__oxamount->value}],
'position': [{$smarty.foreach.gtmArticles.iteration}]
}[{if !$smarty.foreach.gtmArticles.last}],[{/if}]
[{/foreach}]
]
}
});
})
</script>
[{/strip}]
[{$smarty.block.parent}]

View File

@ -2,26 +2,24 @@
[{assign var="gtmProduct" value=$oView->getProduct()}]
[{assign var="gtmCategory" value=$gtmProduct->getCategory()}]
[{assign var="gtmManufacturer" value=$gtmProduct->getManufacturer()}]
[{strip}][{/strip}]
<script>
dataLayer.push({"event": null, "eventLabel": null, "ecommerce": null}); /* Clear the previous ecommerce object. */
dataLayer.push({
'event': 'ee.detail',
'event': 'view_item',
'eventLabel':'Product View',
'ecommerce': {
'currencyCode': '[{$currency->name}]',
'detail': {
'products': [
{
'name': '[{$gtmProduct->oxarticles__oxtitle->value}]',
'id': '[{$gtmProduct->oxarticles__oxartnum->value}]',
'price': [{$gtmProduct->oxarticles__oxprice->value}],
'brand': '[{if $gtmManufacturer}][{$gtmManufacturer->oxmanufacturers__oxtitle->value}][{/if}]',
'category': '[{if $gtmCategory}][{$gtmCategory->getLink()|parse_url:5|ltrim:"/"|rtrim:"/"}][{else}]-[{/if}]',
'variant': '[{if $gtmProduct->oxarticles__oxvarselect->value}][{$gtmProduct->oxarticles__oxvarselect->value}][{/if}]'
}
]
}
'currency': '[{$currency->name}]',
'items': [
{
'item_name': '[{$gtmProduct->oxarticles__oxtitle->value}]',
'item_id': '[{$gtmProduct->oxarticles__oxartnum->value}]',
'item_brand': '[{if $gtmManufacturer}][{$gtmManufacturer->oxmanufacturers__oxtitle->value}][{/if}]',
'item_category': '[{if $gtmCategory}][{$gtmCategory->getLink()|parse_url:5|ltrim:"/"|rtrim:"/"}][{else}]-[{/if}]',
'item_variant': '[{if $gtmProduct->oxarticles__oxvarselect->value}][{$gtmProduct->oxarticles__oxvarselect->value}][{/if}]',
'price': [{$gtmProduct->oxarticles__oxprice->value}]
}
]
}
});
</script>

View File

View File

View File

@ -1,41 +1,58 @@
[{strip}]
[{$gtmProduct|@var_dump}]
[{* variable $gtmProduct is passed from parent tempalte *}]
[{*
[{assign var="gtmCurrency" value=$oView->getActCurrency()}]
[{assign var="gtmManufacturer" value=$gtmProduct->getManufacturer()}]
[{assign var="gtmCategory" value=$gtmProduct->getCategory()}]
<script type="text/javascript">
[{$smarty.block.parent}]
var itemCategories = '[{if $gtmCategory}][{$gtmCategory->getLink()|parse_url:5|ltrim:"/"|rtrim:"/"}][{else}]no category[{/if}]'.split('/');
//console.log(itemCategories);
var _gtmProduct = {
'item_name': '[{$gtmProduct->oxarticles__oxtitle->value}]',
'item_id': '[{$gtmProduct->oxarticles__oxartnum->value}]',
'price': '[{$gtmProduct->oxarticles__oxprice->value}]',
'item_brand': '[{if $gtmManufacturer}][{$gtmManufacturer->oxmanufacturers__oxtitle->value}][{/if}]',
'item_variant': '[{if $gtmProduct->oxarticles__oxvarselect->value}][{$gtmProduct->oxarticles__oxvarselect->value}][{/if}]',
'item_category': itemCategories[0] || 'no category',
'item_category_2': itemCategories[1] || '',
'item_category_3': itemCategories[2] || '',
'item_category_4': itemCategories[3] || '',
[{*$gtmProduct|get_class_methods|dumpvar*}]
[{capture assign=d3_ga4_add_to_cart}]
$("#toBasket").click(function(event) {
[{*event.preventDefault();*}]
let iArtQuantity = $("#amountToBasket").val();
dataLayer.push({
'isAddToBasket': true,
'event':'add_to_cart',
'eventLabel': 'add_to_cart',
'ecommerce': {
'currency': "[{$currency->name}]",
'value': iArtQuantity*[{$gtmProduct->getFieldData('oxprice')}],
'items': [
{
'item_id': '[{$gtmProduct->getFieldData('oxartnum')}]',
'item_name': '[{$gtmProduct->getFieldData('oxtitle')}]',
'price': '[{$gtmProduct->getFieldData('oxprice')}]',
'item_brand': '[{if $gtmManufacturer}][{$gtmManufacturer->oxmanufacturers__oxtitle->value}][{/if}]',
'item_variant': '[{if $gtmProduct->getFieldData('oxvarselect')}][{$gtmProduct->getFieldData('oxvarselect')}][{/if}]',
'item_category': itemCategories[0] || 'no category',
'item_category_2':itemCategories[1] || '',
'item_category_3':itemCategories[2] || '',
'item_category_4':itemCategories[3] || '',
[{if false}]
[{* ??? what *}]
'item_list_name': 'Search Results', // If associated with a list selection.
'item_list_id': 'SR123', // If associated with a list selection.
'index': 1, // If associated with a list selection.
[{/if}]
'quantity': '1'
};
'quantity': iArtQuantity
}
]
}
});
});
console.log(_gtmProduct);
dataLayer.push({
'event':'ecommerce',
'ga4event': 'add_to_cart',
'ecommerce': {
'items': [ _gtmProduct ]
}
});
[{/capture}]
[{oxscript add=$d3_ga4_add_to_cart}]
[{strip}]
[{* variable $gtmProduct is passed from parent tempalte *}]
[{assign var="gtmCurrency" value=$oView->getActCurrency()}]
[{assign var="gtmManufacturer" value=$gtmProduct->getManufacturer()}]
[{assign var="gtmCategory" value=$gtmProduct->getCategory()}]
<script>
dataLayer.push({"event": null, "eventLabel": null, "ecommerce": null}); /* Clear the previous ecommerce object. */
let itemCategories = '[{if $gtmCategory}][{$gtmCategory->getLink()|parse_url:5|ltrim:"/"|rtrim:"/"}][{else}]no category[{/if}]'.split('/');
</script>
*}]
[{/strip}]

View File

View File

View File

View File

@ -0,0 +1,36 @@
[{strip}]
<script type="text/javascript">
window.dataLayer = window.dataLayer || [];
dataLayer.push({ ecommerce: null });
dataLayer.push({
[{assign var="oBasket" value=$order->getBasket()}]
[{assign var="iVat" value=0}]
'event':'purchase',
'ecommerce':{
'purchase':{
'actionField':{
'id': [{$order->getFieldData('oxordernr')}],
'ordernr': [{$order->getFieldData('oxtotalordersum')}],
'tax': [{$order->d3GetSumOrderVat()}],
'shipping': [{$order->getFieldData('oxdelcost')}],
'currency': "[{$order->getFieldData('oxcurrency')}]"
},
'products':[
[{foreach from=$order->getOrderArticles() item=listItem}]
[{assign var="orderArticle" value=$listItem->getArticle()}]
{
'item_id': "[{$listItem->getFieldData('oxartnum')}]",
'item_name': "[{$listItem->getFieldData('oxtitle')}]",
'currency': "[{$order->getFieldData('oxcurrency')}]",
'articleVat': [{$orderArticle->getArticleVat()}],
'price': [{$orderArticle->getBasePrice()}],
'quantity': [{$listItem->getFieldData('oxamount')}]
},
[{/foreach}]
]
}
}
});
</script>
[{/strip}]

View File

View File

@ -0,0 +1,32 @@
[{$smarty.block.parent}]
[{assign var="gtmProducts" value=$oView->getArticleList()}]
[{if $gtmProducts|@count}]
[{strip}]
<script>
dataLayer.push({"event": null, "eventLabel": null, "ecommerce": null}); /* Clear the previous ecommerce object. */
dataLayer.push({
'event': 'view_search_result',
'eventLabel':'view_search_result',
'ecommerce': {
'search_term': '[{$searchparamforhtml}]',
'items': [
[{foreach from=$gtmProducts name="gtmProducts" item="gtmProduct"}]
[{assign var="gtmManufacturer" value=$gtmProduct->getManufacturer()}]
[{if !$gtmCategory}][{assign var="gtmCategory" value=$gtmProduct->getCategory()}][{/if}]
{
'item_id': '[{$gtmProduct->getFieldData("oxartnum")}]',
'item_name': '[{$gtmProduct->getFieldData("oxtitle")}]',
'price': [{$gtmProduct->oxarticles__oxprice->value|default:'0'}],
'item_brand': '[{if $gtmManufacturer}][{$gtmManufacturer->oxmanufacturers__oxtitle->value}][{/if}]',
'item_category': '[{if $gtmCategory}][{$gtmCategory->getLink()|parse_url:5|ltrim:"/"|rtrim:"/"}][{else}]-[{/if}]',
'quantity': 1
}[{if !$smarty.foreach.gtmProducts.last}],[{/if}]
[{/foreach}]
]
}
});
</script>
[{/strip}]
[{/if}]

View File

View File

View File

View File

View File

View File

@ -1,12 +1,18 @@
[{assign var="gtmProducts" value=$products}]
[{assign var="breadCrumb" value=''}]
[{if $gtmProducts|@count}]
[{strip}]
<script>
/* ga4 */
dataLayer.push({ecommerce: null});
dataLayer.push({
'event':'GA4_event',
'event':'view_item_list',
'event_name': 'view_item_list',
'ecommerce': {
'item_list_id': '[{$oView->getCategoryId()}]',
'item_list_name': '[{foreach from=$oView->getBreadCrumb() item=sCrum}][{if $sCrum.title }][{$breadCrumb|cat:$sCrum.title|cat:" > "}][{/if}][{/foreach}]',
'items': [
[{foreach from=$gtmProducts name="gtmProducts" item="gtmProduct"}]
[{assign var="gtmManufacturer" value=$gtmProduct->getManufacturer()}]
@ -23,29 +29,6 @@
]
}
});
/* ua */
dataLayer.push({ecommerce: null});
dataLayer.push({
'event':'UA_event',
'event_name': 'view_item_list',
'ecommerce': {
'currencyCode':'EUR',
'impressions': [
[{foreach from=$gtmProducts name="gtmProducts" item="gtmProduct"}]
[{assign var="gtmManufacturer" value=$gtmProduct->getManufacturer()}]
[{if !$gtmCategory}][{assign var="gtmCategory" value=$gtmProduct->getCategory()}][{/if}]
{
'id': '[{$gtmProduct->getFieldData("oxartnum")}]',
'name': '[{$gtmProduct->getFieldData("oxtitle")}]',
'price': [{$gtmProduct->oxarticles__oxprice->value|default:'0'}],
'brand': '[{if $gtmManufacturer}][{$gtmManufacturer->oxmanufacturers__oxtitle->value}][{/if}]',
'category': '[{if $gtmCategory}][{$gtmCategory->getLink()|parse_url:5|ltrim:"/"|rtrim:"/"}][{else}]-[{/if}]',
'position': [{$smarty.foreach.gtmProducts.iterator|default:1}]
}[{if !$smarty.foreach.gtmProducts.last}],[{/if}]
[{/foreach}]
]
}
});
</script>
[{/strip}]
[{/if}]

View File

View File

@ -1,29 +0,0 @@
[{strip}]
[{assign var="gtmCategory" value=$gtmProduct->getCategory()}]
[{assign var="gtmManufacturer" value=$gtmProduct->getManufacturer()}]
<script>
/* UA */
dataLayer.push({ecommerce: null});
dataLayer.push({
'event': 'UA_ecommerce',
'event_name': 'Impression',
'ecommerce': {
'currencyCode': '[{$currency->name}]',
'impressions': [
{
'name': '[{$gtmProduct->oxarticles__oxtitle->value}]',
'id': '[{$gtmProduct->oxarticles__oxartnum->value}]',
'price': [{$gtmProduct->oxarticles__oxprice->value}],
'brand': '[{if $gtmManufacturer}][{$gtmManufacturer->oxmanufacturers__oxtitle->value}][{/if}]',
'category': '[{if $gtmCategory}][{$gtmCategory->getLink()|parse_url:5|ltrim:"/"|rtrim:"/"}][{else}]no category[{/if}]',
'variant': '[{if $gtmProduct->oxarticles__oxvarselect->value}][{$gtmProduct->oxarticles__oxvarselect->value}][{/if}]'
[{if $list && $position}],
'list': '[{$list}]',
'position': [{"_"|str_replace:"":$position}]
[{/if}]
}
]
}
});
</script>
[{/strip}]

View File

@ -1,62 +0,0 @@
[{strip}]
[{assign var="gtmCartArticles" value=$oView->getBasketArticles()}]
<script>
dataLayer.push({"event": null, "eventLabel": null, "ecommerce": null});
dataLayer.push({
"event":"enhanced-ecommerce",
"ecommerce": {
"checkout": {
"actionField": {"step":1},
"products": [
[{foreach key=basketindex from=$oxcmp_basket->getContents() item=basketitem name=gtmCartContents}]
[{assign var="_price" value=$basketitem->getPrice()}]
{
'id':'[{$gtmCartArticles[$basketindex]->oxarticles__oxartnum->value}]',
'name': '[{$gtmCartArticles[$basketindex]->oxarticles__oxtitle->value}]',
'variant':'[{$gtmCartArticles[$basketindex]->oxarticles__oxvarselect->value}]',
'price': [{$_price->getPrice()}],
'quantity':[{$basketitem->getAmount()}],
'position':[{$smarty.foreach.gtmCartContents.index}]
}[{if !$smarty.foreach.gtmCartContents.last}],[{/if}]
[{/foreach}]
]
}
}
});
var gtmCartContents = {
[{foreach key=basketindex from=$oxcmp_basket->getContents() item=basketitem name=gtmCartContents}]
'[{$basketindex}]':{
'id':'[{$gtmCartArticles[$basketindex]->oxarticles__oxartnum->value}]'
}[{if !$smarty.foreach.gtmCartContents.last}],[{/if}]
[{/foreach}]
};
[{capture name="removeFromBasket"}]
$("#basketRemove").on("click", function() {
var _checked = [],
_products = [];
$("input:checkbox:checked[name^='aproducts'][name*='remove']").each(function() { _checked.push($(this).attr('name').replace("aproducts[","").replace("][remove]","")); });
if(_checked.length == 0) return;
_checked.forEach(function(_oxid) { _products.push({ 'id':gtmCartContents[_oxid].id}) });
dataLayer.push({
'event':'ee.removeFromCart',
'ecommerce': {
'currencyCode': '[{$currency->name}]',
'remove': {
'products': _products
}
}
});
});
/*
*/
[{/capture}]
[{oxscript add=$smarty.capture.removeFromBasket}]
</script>
[{/strip}]
[{$smarty.block.parent}]

View File

@ -1,13 +0,0 @@
<script>
dataLayer.push({
'event':'ee.checkout',
'eventLabel':'Checkout 2',
'ecommerce': {
'checkout': { 'actionField': {
'step': 2,
'option':'[{oxmultilang ident="VT_GTM_EE_LOGINOPTION"|cat:$oView->getLoginOption()}]'
} }
}
});
</script>
[{$smarty.block.parent}]

View File

@ -1,8 +0,0 @@
<script>
dataLayer.push({
'event': 'ee.checkout',
'eventLabel': 'Checkout 3',
'ecommerce': {'checkout': {'actionField': {'step': 3}}}
});
</script>
[{$smarty.block.parent}]

View File

@ -1,8 +0,0 @@
<script>
dataLayer.push({
"event": "ee.checkout",
'eventLabel': 'Checkout 4',
"ecommerce": {"checkout": {"actionField": {"step": 4}}}
});
</script>
[{$smarty.block.parent}]

View File

@ -1,44 +0,0 @@
<script>
[{*
dataLayer.push({
'event': 'ee.checkout',
'eventLabel':'Checkout 5',
'ecommerce': {'checkout': {'actionField': {'step': 5}}}
});
*}]
[{assign var="_gtmOrder" value=$oView->getOrder()}]
[{assign var="_gtmBasket" value=$_gtmOrder->getBasket()}]
[{assign var="_gtmArticles" value=$_gtmOrder->getOrderArticles()}]
dataLayer.push({
'event': 'ee.transaction',
'eventLabel':'[{oxmultilang ident="ORDER_COMPLETED"}]',
'ecommerce': {
'purchase': {
'actionField': {
'id':'[{$_gtmOrder->oxorder__oxordernr->value}]',
'affiliation':'[{$oxcmp_shop->oxshops__oxname->value}]',
'revenue':'[{$_gtmOrder->oxorder__oxtotalordersum->value}]',
'tax':'[{math equation="x+y" x=$_gtmOrder->oxorder__oxartvatprice1->value y=$_gtmOrder->oxorder__oxartvatprice2->value }]',
'shipping':'[{$_gtmOrder->oxorder__oxdelcost->value}]'
/*'coupon':'CANO25' //if a coupon code was used for this order*/
},
'products':[
[{foreach key="_index" from=$_gtmBasket->getContents() item="_gtmBasketitem" name="gtmTransactionProducts"}]
[{assign var="_price" value=$_gtmBasketitem->getPrice()}]
{
'id':'[{$_gtmArticles[$_index]->oxarticles__oxartnum->value}]',
'name': '[{$_gtmArticles[$_index]->oxarticles__oxtitle->value}]',
'variant':'[{$_gtmArticles[$_index]->oxarticles__oxvarselect->value}]',
'price': [{$_price->getPrice()}],
'item_price': [{$_price->getPrice()}],
'quantity':[{$_gtmBasketitem->getAmount()}],
'position':[{$smarty.foreach.gtmTransactionProducts.iteration}]
}[{if !$smarty.foreach.gtmTransactionProducts.last}],[{/if}]
[{/foreach}]
]
}
}
});
</script>
[{$smarty.block.parent}]

30
CHANGELOG.md Normal file
View File

@ -0,0 +1,30 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased](https://git.d3data.de/D3Public/MyModule/compare/1.1.0.0...rel_1.x)
## [1.1.0.0](https://git.d3data.de/D3Public/MyModule/compare/1.0.0.0...1.1.0.0) - 2022-07-26
### Added
- another feature
### Changed
- changed old code
### Deprecated
- ...
### Removed
- ...
### Fixed
- ...
### Security
- ...
## [1.0.0.0](https://git.d3data.de/D3Public/MyModule/releases/tag/1.0.0.0) - 2022-07-25
### Added
- implemented features

18
IntelliSenseHelper.php Normal file
View File

@ -0,0 +1,18 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
*/
namespace D3\GoogleAnalytics4\Modules\Core{
class ViewConfig_parent extends \OxidEsales\Eshop\Core\ViewConfig{}
}

View File

@ -1,97 +1,123 @@
<?php
/*
* vanilla-thunder/oxid-module-gtm
* Google Tag Manager Integration for OXID eShop v6.2+
*
* 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;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
*/
namespace VanillaThunder\GoogleTagManager\Application\Extend;
use OxidEsales\Eshop\Application\Controller\FrontendController;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Configuration\Bridge\ModuleSettingBridgeInterface;
class ViewConfig extends ViewConfig_parent
{
// Google Tag Manager Container ID
private $sContainerId = null;
public function getGtmContainerId()
{
if ( $this->sContainerId === null ) {
$this->sContainerId = ContainerFactory::getInstance()
->getContainer()
->get(ModuleSettingBridgeInterface::class)
->get('vt_gtm_containerid', 'vt-gtm');
}
return $this->sContainerId;
}
public function getGtmDataLayer()
{
if( !$this->getGtmContainerId() ) return "[]";
$oConfig = Registry::getConfig();
$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" )
];
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);
/*
// --- Produktdaten ---
$transactionProducts = [];
foreach($oOrder->getOrderArticles() as $_prod ) $transactionProducts[] = [
'name' => '', // (erforderlich) Produktname String
'sku' => '', // (erforderlich) Produkt-SKU String
'category' => '', // (optional) Produktkategorie String
'price' => '', // (erforderlich) Preis pro Einheit Numerischer Wert
'quantity' => '' // (erforderlich) Anzahl der Artikel Numerischer Wert
];
// --- Transaktionsdaten ---
$dataLayer['transactionId'] = $oOrder->oxorder__oxordernr->value; // (erforderlich) Eindeutige Transaktionskennung String
$dataLayer['transactionAffiliation'] = $oShop->oxshops__oxname->value; // (optional) Partner oder Geschäft String
$dataLayer['transactionTotal'] = $oOrder->oxorder__oxtotalordersum->value; // (erforderlich) Gesamtwert der Transaktion Numerischer Wert
$dataLayer['transactionShipping'] = $oOrder->oxorder__oxdelcost->value; // (optional) Versandkosten fĂĽr die Transaktion Numerischer Wert
$dataLayer['transactionTax'] = ''; // (optional) Steuerbetrag fĂĽr die Transaktion Numerischer Wert
$dataLayer['transactionProducts'] = $transactionProducts; // (optional) Liste der bei der Transaktion erworbenen Artikel Array von Produktobjekten
*/
}
public function isPromotionList($listId)
{
$oConfig = Registry::getConfig();
$aPromotionListIds = $oConfig->getConfigParam("") ?? [ 'bargainItems', 'newItems', 'topBox', 'alsoBought', 'accessories', 'cross' ];
}
<?php
/*
* vanilla-thunder/oxid-module-gtm
* Google Tag Manager Integration for OXID eShop v6.2+
*
* 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;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
*/
namespace D3\GoogleAnalytics4\Modules\Core;
use OxidEsales\Eshop\Application\Controller\FrontendController;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Configuration\Bridge\ModuleSettingBridgeInterface;
class ViewConfig extends ViewConfig_parent
{
// Google Tag Manager Container ID
private $sContainerId = null;
public function getGtmContainerId()
{
if ($this->sContainerId === null)
{
$this->sContainerId = $this->getConfig()->getConfigParam('vt_gtm_sContainerID');
}
return $this->sContainerId;
}
private $blGA4enabled = null;
public function isGA4enabled()
{
if ($this->blGA4enabled === null)
{
$this->sContainerId = $this->getConfig()->getConfigParam('vt_gtm_blEnableGA4');
}
return $this->blGA4enabled;
}
public function getGtmDataLayer()
{
if (!$this->getGtmContainerId()) return "[]";
$oConfig = Registry::getConfig();
$oView = $oConfig->getTopActiveView();
/** @var FrontendController $oShop */
//$oShop = oxRegistry::getConfig()->getActiveShop(); /** @var oxShop $oShop */
$oUser = $oConfig->getUser();
$cl = $this->getTopActionClassName();
$aPageTypes = [
"content" => "cms",
"details" => "product",
"alist" => "listing",
"search" => "listing",
"basket" => "checkout",
"user" => "checkout",
"payment" => "checkout",
"order" => "checkout",
"thankyou" => "checkout",
];
$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
return json_encode([$dataLayer], JSON_PRETTY_PRINT);
/*
// --- Produktdaten ---
$transactionProducts = [];
foreach($oOrder->getOrderArticles() as $_prod ) $transactionProducts[] = [
'name' => '', // (erforderlich) Produktname String
'sku' => '', // (erforderlich) Produkt-SKU String
'category' => '', // (optional) Produktkategorie String
'price' => '', // (erforderlich) Preis pro Einheit Numerischer Wert
'quantity' => '' // (erforderlich) Anzahl der Artikel Numerischer Wert
];
// --- Transaktionsdaten ---
$dataLayer['transactionId'] = $oOrder->oxorder__oxordernr->value; // (erforderlich) Eindeutige Transaktionskennung String
$dataLayer['transactionAffiliation'] = $oShop->oxshops__oxname->value; // (optional) Partner oder Geschäft String
$dataLayer['transactionTotal'] = $oOrder->oxorder__oxtotalordersum->value; // (erforderlich) Gesamtwert der Transaktion Numerischer Wert
$dataLayer['transactionShipping'] = $oOrder->oxorder__oxdelcost->value; // (optional) Versandkosten fĂĽr die Transaktion Numerischer Wert
$dataLayer['transactionTax'] = ''; // (optional) Steuerbetrag fĂĽr die Transaktion Numerischer Wert
$dataLayer['transactionProducts'] = $transactionProducts; // (optional) Liste der bei der Transaktion erworbenen Artikel Array von Produktobjekten
*/
}
public function triggerGA4events()
{
// general events
}
public function isPromotionList($listId)
{
$oConfig = Registry::getConfig();
$aPromotionListIds = $oConfig->getConfigParam("") ?? ['bargainItems', 'newItems', 'topBox', 'alsoBought', 'accessories', 'cross'];
}
}

129
README.md
View File

@ -1,61 +1,96 @@
# [vt] Google Tag Manager
Google Tag Manager integration for OXID eShop v6.2 und höher
module version 0.2.0 ( 2018-12-04 )
[![deutsche Version](https://logos.oxidmodule.com/de2_xs.svg)](README.md)
# Installation
* ``composer require vanilla-thunder/oxid-module-gtm --no-update``
# ![D3 Logo](https://logos.oxidmodule.com/d3logo_24x24.svg) Google-Analytics 4 fĂĽr OXID eShop
* Inhalt von "copy_this" in den Shop hochladen
* Modul aktivieren und Moduleinstellungen konfigurieren
Dieses Modul bietet die Möglichkeit in Ihrem OXID eShop (6.x) die neue 'Property' Google Analytics 4 (GA4) von Google
zu integrieren.
Hierfür stehen Ihnen verschiedene 'templates' zur verfügung, mit denen Sie bestimmte Events tracken können.
Beispiele dafĂĽr sind: view_item, add_to_basket, purchase, ...
# Tag Manager konfigurieren:
+ https://support.google.com/tagmanager/answer/9442095
WeiterfĂĽhrende Informationen: https://developers.google.com/analytics/devguides/collection/ga4
## Inhaltsverzeichnis
- [Installation](#installation)
- [Verwendung](#verwendung)
- [Changelog](#changelog)
- [Lizenz](#lizenz)
## Installation
Dieses Paket erfordert einen mit Composer installierten OXID eShop in einer in der [composer.json](composer.json) definierten Version.
Bitte tragen Sie den folgenden Abschnitt in die `composer.json` Ihres Projektes ein:
```
"extra": {
"oxideshop": {
"blacklist-filter": [
"*.md",
"composer.json",
".php-cs-fixer.php",
"*.xml",
"*.neon"
],
"target-directory": "d3/googleanalytics"
}
```
Ă–ffnen Sie eine Kommandozeile und navigieren Sie zum Stammverzeichnis des Shops (Elternverzeichnis von source und vendor). FĂĽhren Sie den folgenden Befehl aus. Passen Sie die Pfadangaben an Ihre Installationsumgebung an.
```bash
php composer require d3/google-analytics4:^1
```
Sofern nötig, bestätigen Sie bitte, dass Sie `package-name` erlauben, Code auszuführen.
Aktivieren Sie das Modul im Shopadmin unter "Erweiterungen -> Module".
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.
## Verwendung
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):**
+ Triggertyp: Benutzerdefiniertes Ereignis
+ Ereignisname: ``ee\..*``
+ Übereinstimmung mit regulärem Ausdruck verwenden
+ Diesen Trigger auslösen bei: Alle benutzerdefinierten Ereignisse
Nach erfolgreicher Installation finden Sie in Ihrem Shop-Admin unter "Erweiterungen > Module"
den Eintrag 'Google Analytics 4'.
Aktivieren Sie dieses Modul, um die Funktionalitäten nutzen zu können.
**"EE-Tag" fĂĽr Google Analytics Enhanced Ecommerce:**
+ Tag-Typ: Google Analytics - Universal Analytics
+ Tracking-Typ: Ereignis
+ Aktion: {{Event}}
+ Label: {{Event Label}}
+ Trigger : EE-Trigger
Navigieren Sie danach zum Reiter 'Einstell.'.
Tragen Sie die nötige sog. 'Container ID' ein. Diese sieht in etwa so aus: 'GTM-W34LLOP'.
Eine Video-Anleitung mit der kompletten Google Analytics Einrichtung folgt in KĂĽrze.
Aktivieren Sie GA4 selbst, indem Sie dieses direkt darunter anhaken.
### Google Analytics 4 Referenz
https://developers.google.com/tag-manager/ecommerce-ga4
---
Sie nutzen einen eigenen, als Modul im Shop installierten, Cookie-manager? Dann tragen Sie in den Folgeeinstellungen
unter "Cookie Manager Einstellungen", die Cookie-ID des zugehörigen Cookies ein. Und aktivieren Sie diese Weiche,
indem Sie den Haken bei "Eigenen Cookie Manager nutzen?" setzen.
### LICENSE AGREEMENT
[bla] tag-manager
Copyright (C) 2018 bestlife AG
info: oxid@bestlife.ag
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;
either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
## Changelog
Siehe [CHANGELOG](CHANGELOG.md) fĂĽr weitere Informationen.
## Beitragen
Wenn Sie einen Verbesserungsvorschlag haben, legen Sie einen Fork des Repositories an und erstellen Sie einen Pull Request. Alternativ können Sie einfach ein Issue erstellen. Fügen Sie das Projekt zu Ihren Favoriten hinzu. Vielen Dank.
- Erstellen Sie einen Fork des Projekts
- Erstellen Sie einen Feature Branch (git checkout -b feature/AmazingFeature)
- Fügen Sie Ihre Änderungen hinzu (git commit -m 'Add some AmazingFeature')
- Ăśbertragen Sie den Branch (git push origin feature/AmazingFeature)
- Ă–ffnen Sie einen Pull Request
## Lizenz
(Stand: 06.05.2021)
Vertrieben unter der GPLv3 Lizenz.
```
Copyright (c) D3 Data Development (Inh. Thomas Dartsch)
Diese Software wird unter der GNU GENERAL PUBLIC LICENSE Version 3 vertrieben.
```
Die vollständigen Copyright- und Lizenzinformationen entnehmen Sie bitte der [LICENSE](LICENSE.md)-Datei, die mit diesem Quellcode verteilt wurde.
## weitere Lizenzen und Nutzungsbedingungen
...

67
__README.md Normal file
View File

@ -0,0 +1,67 @@
# [D3] Google Tag Manager
Google Tag Manager integration for OXID eShop v6.x
## Installation
* ``composer require vanilla-thunder/oxid-module-gtm --no-update``
* Modul aktivieren und Moduleinstellungen 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/`.
### aktuell zu beachtende Blöcke
- Suchergebnisse: search_results
- (muss hinzugefĂĽgt werden) aList: d3Ga4_view_item_list
- Detailseite: details_productmain_title
- add_to_basket-button: details_productmain_tobasket
- Warenkorb: checkout_basket_main
- Purchase | abgeschlossener Kauf: checkout_thankyou_main
## Universal Analytics Events
**"EE-Trigger" fĂĽr Ecomemrce-Tags (Beispiel fĂĽr Google Tag Manager):**
+ Triggertyp: Benutzerdefiniertes Ereignis
+ Ereignisname: ``ee\..*``
+ Übereinstimmung mit regulärem Ausdruck verwenden
+ Diesen Trigger auslösen bei: Alle benutzerdefinierten Ereignisse
**"EE-Tag" fĂĽr Google Analytics Enhanced Ecommerce:**
+ Tag-Typ: Google Analytics - Universal Analytics
+ Tracking-Typ: Ereignis
+ Aktion: {{Event}}
+ Label: {{Event Label}}
+ Trigger : EE-Trigger
## 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:
### LICENSE AGREEMENT
[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;
either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>

View File

@ -1,8 +1,19 @@
{
"name": "vanilla-thunder/oxid-module-gtm",
"description": "Google Tag Manager with new Google Analytics 4 for OXID eShop v6.2+<br/>more about GA4: <a href='https://developers.google.com/tag-manager/ecommerce-ga4' target='_blank'>Ecommerce (GA4) Developer Guide</a>",
"name": "d3/google-analytics4",
"description": "Google Tag Manager with new Google Analytics 4 for OXID eShop v6",
"type": "oxideshop-module",
"homepage": "https://github.com/vanilla-thunder/oxid-module-gtm",
"keywords": [
"oxid",
"modules",
"eShop",
"d3",
"google",
"ga4",
"googleanalytics",
"gtm",
"configuration"
],
"homepage": "https://www.d3data.de",
"license": [
"GPL-3.0"
],
@ -10,21 +21,36 @@
{
"name": "Marat Bedoev",
"email": "hello@mb-dev.pro"
},
{
"name": "D3 Data Development (Inh. Thomas Dartsch)",
"email": "info@shopmodule.com",
"homepage": "https://www.d3data.de"
}
],
"support": {
"email": "support@shopmodule.com"
},
"extra": {
"oxideshop": {
"target-directory": "vt/GoogleTagManager"
"blacklist-filter": [
"*.md",
"composer.json",
".php-cs-fixer.php",
"*.xml",
"*.neon"
],
"target-directory": "d3/googleanalytics4"
}
},
"require": {
"php": ">=7.1",
"oxid-esales/oxideshop-ce": "^v6.2",
"oxid-esales/oxideshop-ce": "v6.0 - 6.3",
"google/apiclient":" ^2.0"
},
"autoload": {
"psr-4": {
"VanillaThunder\\": "../../../source/modules/vt"
"D3\\GoogleAnalytics4\\": "../../../source/modules/d3/googleanalytics4"
}
}
}

208
metadata.php Normal file → Executable file
View File

@ -1,156 +1,180 @@
<?php
/**
* vanilla-thunder/oxid-module-gtm
* Google Tag Manager Integration for OXID eShop v6.2+
*
* 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;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
**/
use D3\GoogleAnalytics4\Modules\Core\ViewConfig;
use OxidEsales\Eshop\Core\ViewConfig as OEViewConfig;
$sMetadataVersion = '2.1';
$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' => [
\OxidEsales\Eshop\Core\ViewConfig::class => VanillaThunder\GoogleTagManager\Application\Extend\ViewConfig::class
$aModule = [
'id' => 'd3googleanalytics4',
'title' => 'Google Analytics 4',
'description' => "Dieses Modul bietet die Möglichkeit in Ihrem OXID eShop (6.x) die neue 'Property'
Google Analytics 4 (GA4) von Google zu integrieren.<br>
HierfĂĽr stehen Ihnen verschiedene 'templates' zur verfĂĽgung,
mit denen Sie bestimmte Events tracken können.<br>
Beispiele dafĂĽr sind: view_item, add_to_basket, purchase, ...<br><br>
Die Integration und Verbindung zu Google wird mithilfe des gtag (Google Tag Manager) realisiert.<br><br>
WeiterfĂĽhrende Informationen: https://developers.google.com/analytics/devguides/collection/ga4<br>
<hr>
Die Entwicklung basiert auf einem Fork von Marat Bedoev - <a href='https://github.com/vanilla-thunder/oxid-module-gtm'>Github-Link</a>
",
'thumbnail' => 'thumbnail.png',
'version' => '1.0.0.0',
'author' => 'Data Development (Inh.: Thomas Dartsch)',
'email' => 'support@shopmodule.com',
'url' => 'https://www.oxidmodule.com/',
'extend' => [
OEViewConfig::class => 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' => 'd3/googleanalytics4/Application/views/ga4/add_payment_info.tpl',
'add_shipping_info.tpl' => 'd3/googleanalytics4/Application/views/ga4/add_shipping_info.tpl',
'ga4_add_to_cart.tpl' => 'd3/googleanalytics4/Application/views/ga4/add_to_cart.tpl',
'ga4_begin_checkout.tpl' => 'd3/googleanalytics4/Application/views/ga4/begin_checkout.tpl',
'ga4_generate_lead.tpl' => 'd3/googleanalytics4/Application/views/ga4/generate_lead.tpl',
'ga4_login.tpl' => 'd3/googleanalytics4/Application/views/ga4/login.tpl',
'ga4_purchase.tpl' => 'd3/googleanalytics4/Application/views/ga4/purchase.tpl',
'ga4_remove_from_cart.tpl' => 'd3/googleanalytics4/Application/views/ga4/remove_from_cart.tpl',
'ga4_search.tpl' => 'd3/googleanalytics4/Application/views/ga4/search.tpl',
'ga4_select_content.tpl' => 'd3/googleanalytics4/Application/views/ga4/select_content.tpl',
'ga4_select_item.tpl' => 'd3/googleanalytics4/Application/views/ga4/select_item.tpl',
'ga4_select_promotion.tpl' => 'd3/googleanalytics4/Application/views/ga4/select_promotion.tpl',
'ga4_sign_up.tpl' => 'd3/googleanalytics4/Application/views/ga4/sign_up.tpl',
'ga4_view_cart.tpl' => 'd3/googleanalytics4/Application/views/ga4/view_cart.tpl',
'ga4_view_item.tpl' => 'd3/googleanalytics4/Application/views/ga4/view_item.tpl',
'ga4_view_item_list.tpl' => 'd3/googleanalytics4/Application/views/ga4/view_item_list.tpl',
'ga4_view_promotion.tpl' => 'd3/googleanalytics4/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',
'position' => 150
],
// 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'
],
// Lists
// view_item_list
[
'template' => 'widget/product/list.tpl',
'block' => 'd3Ga4_view_item_list',
'file' => '/Application/views/ga4/view_item_list.tpl'
],
// view_search_result
[
'template' => 'page/search/search.tpl',
'block' => 'search_results',
'file' => '/Application/views/ga4/search.tpl'
],
// add_to_cart
[
'template' => 'page/details/inc/productmain.tpl',
'block' => 'details_productmain_tobasket',
'file' => '/Application/views/ga4/add_to_cart.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_blGA4enab',
'type' => 'bool',
'value' => true,
'position' => 1
],
[
'group' => 'vt_gtm_settings',
'name' => 'vt_gtm_enable_ua',
'type' => 'bool',
'value' => true,
'position' => 2
'group' => 'vt_gtm_settings',
'name' => 'vt_gtm_blEnableDebug',
'type' => 'bool',
'value' => false,
'position' => 999
],
[
'group' => 'vt_gtm_settings',
'name' => 'vt_gtm_mpapisecret',
'type' => 'str',
'value' => '',
'position' => 3
'group' => 'vt_gtm_settings_cookiemanager',
'name' => 'vt_gtm_settings_hasOwnCookieManager',
'type' => 'bool',
'value' => false,
'position' => 999
],
[
'group' => 'vt_gtm_settings',
'name' => 'vt_gtm_promotionlistids',
'type' => 'arr',
'value' => [],
'position' => 4
]
'group' => 'vt_gtm_settings_cookiemanager',
'name' => 'vt_gtm_settings_cookieName',
'type' => 'str',
'value' => 'example',
'position' => 999
],
]
];

10
phpstan.neon Normal file
View File

@ -0,0 +1,10 @@
parameters:
scanFiles:
- IntelliSenseHelper.php
- ../../oxid-esales/oxideshop-ce/source/oxfunctions.php
- ../../oxid-esales/oxideshop-ce/source/overridablefunctions.php
level: 9
phpVersion: 70100
checkMissingIterableValueType: false
ignoreErrors:
- '#Psr\\Container\\ContainerExceptionInterface is not subtype of Throwable#'

20
phpunit.xml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="vendor/autoload.php"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage>
<include>
<directory suffix=".php">src</directory>
</include>
<report>
<clover outputFile="build/logs/clover.xml"/>
</report>
</coverage>
<testsuite name="myModule">
<directory>./Tests</directory>
</testsuite>
<logging/>
</phpunit>

BIN
thumbnail.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB