Merge remote-tracking branch 'remotes/origin/rel_2.x'

This commit is contained in:
MaxBuhe01 2024-08-10 13:56:00 +02:00
commit 96e5adbece
26 changed files with 1043 additions and 207 deletions

View File

@ -0,0 +1,85 @@
<?php
declare(strict_types=1);
namespace D3\GoogleAnalytics4\Application\Controller\Admin;
use D3\GoogleAnalytics4\Application\Model\Constants;
use D3\GoogleAnalytics4\Application\Model\ManagerHandler;
use D3\GoogleAnalytics4\Application\Model\ManagerTypes;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\ViewConfig;
class GA4AdminUserInterface_main extends \OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController
{
protected $_sThisTemplate = 'ga4/admin/d3ga4uimain.tpl';
public function render()
{
$return = parent::render();
$this->addTplParam('d3ViewObject', $this);
$this->addTplParam('d3ViewConfObject', Registry::get(ViewConfig::class));
$this->addTplParam('d3ManagerTypeArray', oxNew(ManagerTypes::class)->getManagerList());
$this->addTplParam('d3CurrentCMP', oxNew(ManagerHandler::class)->getCurrManager());
return $return;
}
public function save()
{
parent::save();
$aParams = Registry::getRequest()->getRequestEscapedParameter('editval');
$aCheckBoxParams = [
'_blEnableGa4',
'_blEnableDebug',
'_blEnableConsentMode',
'_blEnableOwnCookieManager',
'_blEnableMeasurementCapabilities',
'_blEnableUsercentricsConsentModeApi',
];
foreach ($aCheckBoxParams as $checkBoxName){
if (isset($aParams['bool'][$checkBoxName])){
$aParams['bool'][$checkBoxName] = true;
}else{
$aParams['bool'][$checkBoxName] = false;
}
}
$this->d3SaveShopConfigVars($aParams);
}
/**
* @param array $aParams
* @return void
*/
protected function d3SaveShopConfigVars(array $aParams)
{
$oConfig = Registry::getConfig();
foreach ($aParams as $sConfigType => $aConfigParams) {
foreach ($aConfigParams as $sParamName => $sParamValue){
if($this->d3GetModuleConfigParam($sParamName) !== $sParamValue){
$oConfig->saveShopConfVar(
$sConfigType,
Constants::OXID_MODULE_ID.$sParamName,
$sParamValue,
$oConfig->getShopId(),
Constants::OXID_MODULE_ID
);
}
}
}
}
/**
* @param string $configParamName
* @return mixed
*/
public function d3GetModuleConfigParam(string $configParamName)
{
return Registry::get(ViewConfig::class)->d3GetModuleConfigParam($configParamName);
}
}

View File

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace D3\GoogleAnalytics4\Application\Model\CMP;
abstract class ConsentManagementPlatformBaseModel extends \OxidEsales\Eshop\Core\Model\BaseModel implements ConsentManagementPlatformInterface
{
public string $sCMPName;
/**
* @return string
*/
public function getCMPName(): string
{
return $this->sCMPName;
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace D3\GoogleAnalytics4\Application\Model\CMP;
interface ConsentManagementPlatformInterface
{
public function getCMPName();
}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace D3\GoogleAnalytics4\Application\Model\CMP;
use D3\GoogleAnalytics4\Application\Model\ManagerTypes;
/**
* Used the OXID Module.
*
* Further information's:
* https://docs.oxid-esales.com/modules/usercentrics/de/latest/einfuehrung.html
*
* Usercentrics homepage:
* https://usercentrics.com
*/
class Usercentrics extends ConsentManagementPlatformBaseModel
{
const sExternalIncludationPublicName = "( Externe Einbindung ) Usercentrics";
const sExternalIncludationInternalName = "usercentrics";
const sModuleIncludationPublicName = "( Modul ) Usercentrics";
const sModuleIncludationInternalName = "oxps_usercentrics";
}

View File

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace D3\GoogleAnalytics4\Application\Model;
class Constants
{
public const OXID_MODULE_ID = 'd3googleanalytics4';
}

View File

@ -8,6 +8,8 @@ use OxidEsales\Eshop\Core\ViewConfig;
class ManagerHandler
{
/**
* Gets current chosen Manager
*
* @return string
*/
public function getCurrManager() :string
@ -20,13 +22,32 @@ class ManagerHandler
$aManagerList = $oManagerTypes->getManagerList();
foreach ($aManagerList as $managerName){
if ($oViewConfig->isModuleActive($managerName)){
return $managerName;
if ($this->getModuleSettingExplicitManagerSelectValue()){
return $this->getExplicitManager();
}
foreach ($aManagerList as $shopModuleId => $publicCMPName){
if ($oViewConfig->isModuleActive($shopModuleId)){
$this->d3SaveShopConfVar($shopModuleId);
return $shopModuleId;
}
}
return $this->getExplicitManager();
return "";
}
/**
* @param string $sParam
* @return void
*/
public function d3SaveShopConfVar(string $sParam){
Registry::getConfig()->saveShopConfVar(
'select',
Constants::OXID_MODULE_ID."_HAS_STD_MANAGER",
$sParam,
Registry::getConfig()->getShopId(),
Constants::OXID_MODULE_ID
);
}
/**
@ -34,7 +55,7 @@ class ManagerHandler
*/
public function getModuleSettingExplicitManagerSelectValue() :string
{
return Registry::getConfig()->getConfigParam('d3_gtm_settings_HAS_STD_MANAGER');
return Registry::get(ViewConfig::class)->d3GetModuleConfigParam('_HAS_STD_MANAGER')?:"";
}
/**
@ -46,8 +67,12 @@ class ManagerHandler
/** @var ManagerTypes $oManagerTypes */
$oManagerTypes = oxNew(ManagerTypes::class);
return $oManagerTypes->isManagerInList($sPotentialManagerName)
$sCMPName = $oManagerTypes->isManagerInList($sPotentialManagerName)
? $sPotentialManagerName
: "NONE";
$this->d3SaveShopConfVar($sCMPName);
return $sCMPName;
}
}

View File

@ -2,41 +2,24 @@
namespace D3\GoogleAnalytics4\Application\Model;
use D3\GoogleAnalytics4\Application\Model\CMP\Usercentrics;
class ManagerTypes
{
#ToDo: make own classes for each of the manager
const EXTERNAL_SERVICE = "externalService";
const NET_COOKIE_MANAGER = "net_cookie_manager";
const EXTERNAL_SERVICE = "eigener Service";
const NET_COOKIE_MANAGER = "Netensio Cookie Manager";
/**
* Further information's:
* https://github.com/aggrosoft/oxid-cookie-compliance
*/
const AGCOOKIECOMPLIANCE = "agcookiecompliance";
const AGCOOKIECOMPLIANCE = "Aggrosoft Cookie Compliance";
/**
* Used the OXID Module.
*
* Further information's:
* https://docs.oxid-esales.com/modules/usercentrics/de/latest/einfuehrung.html
*
* Usercentrics homepage:
* https://usercentrics.com
*/
const USERCENTRICS_MODULE = "oxps_usercentrics";
const CONSENTMANAGER = "Consentmanager";
/**
* manually included usercentrics script
*/
const USERCENTRICS_MANUALLY = "USERCENTRICS";
const COOKIEFIRST = "Cookiefirst";
const CONSENTMANAGER = "CONSENTMANAGER";
const COOKIEFIRST = "COOKIEFIRST";
const COOKIEBOT = "COOKIEBOT";
const COOKIEBOT = "Cookiebot";
/**
* @return array
@ -47,9 +30,9 @@ class ManagerTypes
"externalService" => self::EXTERNAL_SERVICE,
"agcookiecompliance" => self::AGCOOKIECOMPLIANCE,
"net_cookie_manager" => self::NET_COOKIE_MANAGER,
"oxps_usercentrics" => self::USERCENTRICS_MODULE,
"usercentrics" => self::USERCENTRICS_MANUALLY,
"consentmanager" => self::CONSENTMANAGER,
Usercentrics::sModuleIncludationInternalName => Usercentrics::sModuleIncludationPublicName,
Usercentrics::sExternalIncludationInternalName => Usercentrics::sExternalIncludationPublicName,
"cmconsentmanager" => self::CONSENTMANAGER,
"cookiefirst" => self::COOKIEFIRST,
"cookiebot" => self::COOKIEBOT,
];
@ -61,6 +44,6 @@ class ManagerTypes
*/
public function isManagerInList(string $sManager) :bool
{
return in_array($sManager, $this->getManagerList(), true);
return in_array($sManager, array_keys($this->getManagerList()), true);
}
}

View File

@ -0,0 +1,123 @@
<?php
$sLangName = "Deutsch";
// -------------------------------
// RESOURCE IDENTITFIER = STRING
// -------------------------------
$aLang = array(
'charset' => 'UTF-8',
'd3mxgoogleanalytics4' => 'Google Analytics 4',
'd3mxgoogleanalytics4set' => 'Einstellungen',
// Base Translations
'D3BASECONFIG' => 'Grundeinstellungen',
'D3CLOSE' => 'Schließen',
'D3NONE' => '- keinen -',
'D3CONTAINERID' => 'Container-ID',
'D3CONTAINERID_HELP' => '<a target="_blank" href="https://github.com/d3datadevelopment/GoogleAnalytics4/blob/master/Docs/README.md#Container-ID" class="text-muted text-decoration-none"><i class="bi bi-book-half"></i> Was ist die <strong>Container-ID</strong>?</a>',
'D3ACTIVATEMOD' => 'Modul aktivieren',
'D3CNTRLPARAM' => 'Steuerungsparameter',
'D3CNTRLPARAM_HELP' => '<a target="_blank" href="https://github.com/d3datadevelopment/GoogleAnalytics4/blob/master/Docs/README.md#steuerungsparameter" class="text-muted text-decoration-none"><i class="bi bi-book-half"></i> Was ist der <strong>Steuerungsparameter</strong>?</a>',
'D3INACTIVATEMOD' => 'Modul ist nicht aktiv! Es werden keine Funktionen ausgespielt!',
// Usercentrics Dynamische Optionen
'D3USRCNTRCSDYNOPT' => 'Usercentrics Dynamische Optionen',
// Use debug mode?
'D3USEDEBUGMODE' => "Debug-Modus aktivieren",
'D3USEDEBUGMODE_HELP' => "Der <strong>Debug Modus</strong> setzt an alle DataLayer ( also Daten Sammlungen im Frontend )
<strong>'debug_mode': 'true'</strong> und ermöglicht im Google Tag Manager selbst ein detaillierteres
Auswerten des einfließenden Datenstroms.",
// Use Consentmode?
'D3USEGOOGLECONSENTMODE' => "Google Consent Mode 'Default Values' akivieren",
'D3USEGOOGLECONSENTMODE_HELP' => "Der <trong>Consent Mode 'Default Values'</trong> setzt im Frontend,
vor jedem Sammeln und Senden von Daten, einen Befehl der die Bearbeitung der Daten fortlaufend verändert.<br>
<br>
Diese Veränderte Berarbeitung heißt im Detail, dass der Google Tag Manager ( GTM )
bzw. in erster Instanz die Consent Management Platform ( CMP ) keine Daten zur Verarbeitung an Google sendet,
bis ein entsprechendes Zustimmungs-Signal vom Kunden explizit erteilt wurde.<br>
Die CMP ist sogar derartig restriktiv, dass diese den Datenstrom zum GTM ( Vorinstanz zu Google Analytics )
völlig verhindert, solange keine Zustimmung erteilt wurde.<br>
<br>
Ein einfaches anschalten dieser Funktion regelt noch <strong>nicht</strong> die völlige Funktionsweise
aller beteiligten Instanzen; diese bedarf eine detailliertere Konfiguration!<br>",
// Use CMP?
'D3CMPTABTITLE' => 'Cookie Manager Einstellungen',
'D3CMPUSEQ' => 'Consent Management Platform ( CMP ) nutzen?',
'D3CMPUSEQ_HELP' => '"Eine Consent Management Platform ( CMP ) ist eine Software, mit der Website-Betreiber
oder Anbieter von Web-Apps über ein Banner oder ein Pop-up eine datenschutzrechtliche
Einwilligung der Besucher einholen und speichern, bevor Nutzerdaten über
Website-Skripte erfasst werden (Tracking)." <a target="_blank" href="https://de.wikipedia.org/wiki/Consent_Management_Platform">Wikipedia Beschreibung</a><br>
<br>
Um Google Analytics 4 ( <a target="_blank" href="https://marketingplatform.google.com/intl/de/about/analytics/">Google Analytics</a> ) weiterhin nutzen zu können,
und dank fortschreitendem Datenschutz unserer personenbezogener Daten, ist das Nutzen eines konformen CMP
heute zwangläufig nötig.<br>
<br>
Diese konformen CMP sind in
<a target="_blank" href="https://cmppartnerprogram.withgoogle.com/">offizieller Partnerschaft mit Google ( Liste der Partner )</a>
und unterliegen strengen Vorschriften, um ein ordnungsgemäßes Senden und
Verarbeiten der Zustimmung unterliegenden Daten sicher stellen zu können.',
'D3CMP' => 'Consent Management Platform ( CMP ) wählen',
// Usercentrics Config
// activate Individual Default Values
'D3USRCNTRCSCFG_ACT_INDIVDEFVAL' => "Usercentrics individual 'Default Values' aktiveren",
// standard Consent
'D3USRCNTRCSCFG_STD_CNST' => "GTM Standard Consent",
// activate consent mode API
'D3USRCNTRCSCFG_ACT_CNSTMDE_API' => "Usercentrics Consent Mode API aktivieren",
// consent mode api
'D3USRCNTRCSCFG_CNSTMDE_API' => "Consent Mode API",
'D3USRCNTRCSCFG_DOCS' => 'Nähere Infos zu den hier konfigurierbaren Einstellungen entnehmen Sie bitte der offiziellen
Dokumentation von Usercentrics selbst: <a target="_blank" href="https://docs.usercentrics.com/#/consent-mode" class="text-primary"><i class="bi bi-book-half"></i> Dokumentation</a>',
'D3USRCNTRCSCFG_WARNING' => "Bevor Sie hier Anpassungen machen, konsultieren Sie bitte einen technischen Support!<br>
Anpassungen können zu Beeinträchtigungen und Ausfall von Funktionen im Frontend führen!",
// Additional Config
// Server-Side tagging
'D3SERVERSIDETAGGING' => 'Server-Side tagging',
'D3DETAILED_DESC' => 'Detailliertere Erklärung der Funktion',
'D3SERVERSIDETAGGING_HINT' => 'Die Conatiner-ID wird weiterhin unter "Grundeinstellungen" eingetragen!<br><br>
"Serverseitiges Tagging ist eine neue Möglichkeit, mit Google Tag Manager Ihre Anwendung geräteübergreifend zu verwalten.<br>
Servercontainer verwenden dasselbe Tag-, Trigger- und Variablenmodell, das Sie gewohnt sind.<br>
Außerdem bieten sie neue Tools, mit denen Sie Nutzeraktivitäten überall messen können." <br>
<br>
- Quelle <a href="https://developers.google.com/tag-platform/tag-manager/server-side/intro">Developers-Google Server-Side tagging</a><br>
<br>
<strong>Verändern Sie die Werte nur, wenn Sie Server-Side tagging verwenden wollen! Gegebenenfalls fragen Sie einen technischen Ansprechpartner.</strong>
',
'D3SERVERSIDETAGGING_TITLE_ACTIVE' => 'Ausführender code',
'D3SERVERSIDETAGGING_ACTIVE' => 'Diese Domain wird im <strong>aktiven</strong>-code ausgefüht. Das heißt,
dass es sich hierbei um das HTML-Tag <code>script</code> handelt.
Dieses kümmert sich darum, dass die im DataLayer
zusammengefassten Daten an den GTM weitergeleitet werden.<br>
<br>
<h4>Folgend eine Darstellung, was genau ausgetauscht wird</h4>
<pre>
<code>
Vorher:
https://www.googletagmanager.com/gtm.js?id=
Nachher:
{Domain}?id=
</code>
</pre>',
'D3SERVERSIDETAGGING_TITLE_PASSIVE' => '<u>nicht</u>&nbsp;Ausführneder code',
'D3SERVERSIDETAGGING_PASSIVE' => 'Diese Domain wird im <strong>passiven</strong>-code ausgefüht. Das heißt,
dass es sich hierbei um das HTML-Tag <code>noscript</code> handelt.
Dieses wird ausgeführt, wenn aus einem bestimmten Grund
das Javascript nicht ausgeführt wird.<br>
( keine Cookies erlaubt, JavaScript-Unterbindung, ... )
<br>
<h4>Folgend eine Darstellung, was genau ausgetauscht wird</h4>
<pre>
<code>
Vorher:
src="https://www.googletagmanager.com/ns.html?id={Container-ID}"
Nachher:
src="{Domain}?id={Container-ID}"
</code>
</pre>',
);

View File

@ -10,6 +10,8 @@
* @link https://www.oxidmodule.com
*/
use D3\GoogleAnalytics4\Application\Model\Constants as Constants;
$style = '<style type="text/css">
.groupExp a.rc b {font-size:medium;color:#ff3600;}
.groupExp dt .txt,
@ -22,32 +24,87 @@ input.confinput:hover {outline:3px solid #ff3600;}
</style>';
$aLang = [
'charset' => 'UTF-8',
'SHOP_MODULE_d3_gtm_sContainerID' => 'Container ID',
'SHOP_MODULE_GROUP_d3_gtm_settings' => 'Einstellungen',
'SHOP_MODULE_d3_gtm_blGA4enab' => 'GA4 Aktivieren',
'SHOP_MODULE_d3_gtm_blUAenabled' => 'UA Aktivieren',
'SHOP_MODULE_d3_gtm_blEnableDebug' => 'Debug-Modus aktivieren',
// STD-Einstellungen
'SHOP_MODULE_GROUP_'.Constants::OXID_MODULE_ID.'_settings' => 'Einstellungen',
'SHOP_MODULE_'. Constants::OXID_MODULE_ID.'_sContainerID' => 'Container ID',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_blGA4enab' => 'GA4 Aktivieren',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_blUAenabled' => 'UA Aktivieren',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_blEnableDebug' => 'Debug-Modus aktivieren',
// Serverside - tagging
'SHOP_MODULE_GROUP_'.Constants::OXID_MODULE_ID.'_serversidetagging' => 'Server-Side tagging',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_serversidetagging_js' => 'Servercontainer Ausführender-Code',
'HELP_SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_serversidetagging_js' => 'Diese Domain wird im <strong>aktiven</strong>-code ausgefüht. Das heißt,
dass es sich hierbei um das HTML-Tag <code>script</code> handelt.
Dieses kümmert sich darum, dass die, im data_layer
zusammengefassten Daten an den GTM weitergeleitet werden.<br>
<br>
<h4>Folgend eine Darstellung, was genau ausgetauscht wird</h4>
<pre>
<code>
Vorher:
https://www.googletagmanager.com/gtm.js?id=
Nachher:
{Domain}?id=
</code>
</pre>
Die Conatiner-ID wird weiterhin im Punkt "Einstellung" eingetragen!
',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_serversidetagging_nojs' => 'Servercontainer NICHT Ausführender-Code<br><br>
"Serverseitiges Tagging ist eine neue Möglichkeit, mit Google Tag Manager Ihre Anwendung geräteübergreifend zu verwalten.<br>
Servercontainer verwenden dasselbe Tag-, Trigger- und Variablenmodell, das Sie gewohnt sind.<br>
Außerdem bieten sie neue Tools, mit denen Sie Nutzeraktivitäten überall messen können." <br>
<br>
- Quelle <a href="https://developers.google.com/tag-platform/tag-manager/server-side/intro">Developers-Google Server-Side tagging</a><br>
<br>
<strong>Verändern Sie die Werte nur, wenn Sie Server-Side tagging verwenden wollen!</strong>
',
'HELP_SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_serversidetagging_nojs' => 'Diese Domain wird im <strong>passiven</strong>-code ausgefüht. Das heißt,
dass es sich hierbei um das HTML-Tag <code>noscript</code> handelt.
Dieses wird ausgeführt, wenn aus einem bestimmten Grund
das Javascript nicht ausgeführt wird.<br>
( keine Cookies erlaubt, JavaScript-Unterbindung, ... )
<br>
<h4>Folgend eine Darstellung, was genau ausgetauscht wird</h4>
<pre>
<code>
Vorher:
src="https://www.googletagmanager.com/ns.html?id={Container-ID}"
Nachher:
src="{Domain}?id={Container-ID}"
</code>
</pre>
Die Conatiner-ID wird weiterhin im Punkt "Einstellung" eingetragen!
',
// for cookie manager settings
'SHOP_MODULE_GROUP_d3_gtm_settings_cookiemanager' => 'Cookie Manager Einstellungen',
'SHOP_MODULE_d3_gtm_settings_hasOwnCookieManager' => 'Cookie Manager nutzen?',
'HELP_SHOP_MODULE_d3_gtm_settings_HAS_STD_MANAGER' => 'Mehr Informationen zu den genannten Coookie-Manager finden Sie auf den folgenden Home-Pages<br><br>
'SHOP_MODULE_GROUP_'.Constants::OXID_MODULE_ID.'_cookiemanager' => 'Cookie Manager Einstellungen',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_hasOwnCookieManager' => 'Cookie Manager nutzen?',
'HELP_SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_HAS_STD_MANAGER' => 'Mehr Informationen zu den genannten Coookie-Manager finden Sie auf den folgenden Home-Pages<br><br>
<a href="https://consentmanager.net/">Consentmanager</a><br>
<a href="https://usercentrics.com/">Usercentrics</a><br>
<a href="https://cookiefirst.com">Cookiefirst</a><br>
<hr>
Bei weiteren Fragen stehen wir gern zur Verfügung! Kontaktieren Sie uns einfach unter <a href="https://www.d3data.de/">https://www.d3data.de/</a>',
'SHOP_MODULE_d3_gtm_settings_HAS_STD_MANAGER' => 'Nutzen Sie eine der folgenden Einbindungen?<br>
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_HAS_STD_MANAGER' => 'Nutzen Sie eine der folgenden Einbindungen?<br>
Dann wählen Sie bitte die zutreffende aus.',
'SHOP_MODULE_d3_gtm_settings_HAS_STD_MANAGER_NONE' => '---',
'SHOP_MODULE_d3_gtm_settings_HAS_STD_MANAGER_CONSENTMANAGER' => 'consentmanager',
'SHOP_MODULE_d3_gtm_settings_HAS_STD_MANAGER_USERCENTRICS' => 'usercentrics',
'SHOP_MODULE_d3_gtm_settings_HAS_STD_MANAGER_COOKIEFIRST' => 'cookiefirst',
'SHOP_MODULE_d3_gtm_settings_HAS_STD_MANAGER_COOKIEBOT' => 'Cookiebot',
'SHOP_MODULE_d3_gtm_settings_controlParameter' => 'Steuerungsparameter',
'HELP_SHOP_MODULE_d3_gtm_settings_controlParameter' => 'Nähere infos zum <a target="_blank" href="https://git.d3data.de/D3Public/GoogleAnalytics4/src/branch/master/Docs">"<strong>Steuerungsparameter</strong>"</a><hr>
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_HAS_STD_MANAGER_NONE' => '---',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_HAS_STD_MANAGER_CONSENTMANAGER' => 'consentmanager',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_HAS_STD_MANAGER_USERCENTRICS' => 'usercentrics',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_HAS_STD_MANAGER_COOKIEFIRST' => 'cookiefirst',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_HAS_STD_MANAGER_COOKIEBOT' => 'Cookiebot',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_controlParameter' => 'Steuerungsparameter',
'HELP_SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_controlParameter' => 'Nähere infos zum <a target="_blank" href="https://git.d3data.de/D3Public/GoogleAnalytics4/src/branch/master/Docs">"<strong>Steuerungsparameter</strong>"</a><hr>
<strong>Beachte:</strong><br>
Sofern Sie die <a target="_blank" href="https://consentmanager.net" style="color: blue">consentmanager</a> CMP verwenden,
bitte ich Sie, gründlichst, die Hinweise der <a target="_blank" href="https://git.d3data.de/D3Public/GoogleAnalytics4/src/branch/master/Docs/CMP/consentmanager.md">Moduldokumentation/Consentmanager</a> zu lesen.
'
',
'SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_blActivateConsentMode' => "Google Consent Mode 'Default Values' aktivieren",
'HELP_SHOP_MODULE_'.Constants::OXID_MODULE_ID.'_blActivateConsentMode' => 'Diese Einstellung ist zu aktivieren, wenn Sie den Google-Consent-Mode ( Einwilligungsmodus ) verwenden wollen.
<hr>
"Im Einwilligungsmodus können Sie Google über den Cookie- oder App-ID-Einwilligungsstatus Ihrer Nutzer informieren.
Mit Tags wird das Verhalten angepasst. Dabei werden die Einstellungen der Nutzer berücksichtigt." ~ <a href="https://support.google.com/google-ads/answer/10000067">Google Einwilligungsmodus</a>',
];

View File

@ -0,0 +1,108 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>[{$title}]</title>
<meta http-equiv="Content-Type" content="text/html; charset=[{$charset}]">
[{if isset($meta_refresh_sec,$meta_refresh_url)}]
<meta http-equiv=Refresh content="[{$meta_refresh_sec}];URL=[{$meta_refresh_url|replace:"&amp;":"&"}]">
[{/if}]
<link rel="shortcut icon" href="[{$oViewConf->getBaseDir()}]favicon.ico">
[{block name="admin_headitem_inccss"}]
<link rel="stylesheet" href="[{$oViewConf->getResourceUrl()}]main.css">
<link rel="stylesheet" href="[{$oViewConf->getResourceUrl()}]colors_[{$oViewConf->getEdition()|lower}].css">
<link rel="stylesheet" type="text/css" href="[{$oViewConf->getResourceUrl()}]yui/build/assets/skins/sam/container.css">
[{/block}]
[{block name="admin_headitem_incjs"}]
<script type="text/javascript" src="[{$oViewConf->getResourceUrl()}]yui/build/utilities/utilities.js"></script>
<script type="text/javascript" src="[{$oViewConf->getResourceUrl()}]yui/build/container/container-min.js"></script>
<script type="text/javascript" src="[{$oViewConf->getResourceUrl()}]yui/oxid-help.js"></script>
[{/block}]
[{block name="admin_headitem_js"}]
<script type="text/javascript">
<!--
// standard messages
var sUnassignMessage = "[{oxmultilang ident='GENERAL_YOUWANTTOUNASSIGN'}]";
var sDeleteMessage = "[{oxmultilang ident='GENERAL_YOUWANTTODELETE'}]";
// class info
var sDefClass = '[{$default_edit}]';
var sActClass = '[{$actlocation}]';
[{if $updatelist == 1}]
window.onload = function ()
{
top.oxid.admin.updateList('[{$oxid}]');
}
[{/if}]
var ajaxpopup = null;
function showDialog( sParams )
{
ajaxpopup = window.open('[{$oViewConf->getSelfLink()|replace:"&amp;":"&"}]'+sParams, 'ajaxpopup', 'width=850,height=680,scrollbars=yes,resizable=yes');
}
function focusPopup()
{
if ( ajaxpopup )ajaxpopup.focus();
}
window.onclick = focusPopup;
function cleanupLongDesc( sValue )
{
if ( sValue == '<br>' || sValue == '<br />' ) {
return '';
}
return sValue;
}
function copyLongDesc( sIdent )
{
var textVal = null;
try {
if ( WPro.editors[sIdent] != null ) {
WPro.editors[sIdent].prepareSubmission();
textVal = cleanupLongDesc( WPro.editors[sIdent].getValue() );
}
} catch(err) {
var varEl = document.getElementById(sIdent);
if (varEl != null) {
textVal = cleanupLongDesc( varEl.value );
}
}
if (textVal == null) {
var varName = 'editor_'+sIdent;
var varEl = document.getElementById(varName);
if (varEl != null) {
textVal = cleanupLongDesc( varEl.value );
}
}
if (textVal != null) {
var oTarget = document.getElementsByName( 'editval['+ sIdent + ']' );
if ( oTarget != null && ( oField = oTarget.item( 0 ) ) != null ) {
oField.value = textVal;
}
}
}
-->
</script>
[{/block}]
</head>
<body>
[{include file="tooltips.tpl"}]
<div id="oxajax_data"></div>
<div class="[{$box|default:'box'}]" style="height: 100%;">
[{include file="inc_error.tpl" Errorlist=$Errors.default}]
<!-- Input help popup -->
<div id="helpTextContainer" class="yui-skin-sam">
<div id="helpPanel"></div>
</div>

View File

@ -0,0 +1,198 @@
[{include file="ga4/admin/d3ga4uiheaditem.tpl" title="GENERAL_ADMIN_TITLE"|oxmultilangassign}]
<style>
body {
background-image: linear-gradient(to top, #d5d4d0 0%, #d5d4d0 1%, #eeeeec 31%, #efeeec 75%, #e9e9e7 100%);
}
</style>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
[{if $readonly}]
[{assign var="readonly" value="readonly disabled"}]
[{else}]
[{assign var="readonly" value=""}]
[{/if}]
<div>
<form name="d3gtmformedit" id="d3gtmformedit" action="[{$oViewConf->getSelfLink()}]" enctype="multipart/form-data" method="post">
<div class="row">
<div class="col-6">
[{$oViewConf->getHiddenSid()}]
<input type="hidden" name="cl" value="[{$oViewConf->getActiveClassName()}]">
<input type="hidden" name="fnc" value="">
<input type="hidden" name="editlanguage" value="[{$editlanguage}]">
<div class="card mb-5">
<div class="card-header">
[{oxmultilang ident="D3BASECONFIG"}]
</div>
<div class="card-body">
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" value="" name="editval[bool][_blEnableGa4]" [{if $d3ViewObject->d3GetModuleConfigParam('_blEnableGa4')}]checked[{/if}] id="blGA4enab">
<label class="form-check-label" for="flexCheckDefault">
[{oxmultilang ident="D3ACTIVATEMOD"}] [{if false === $d3ViewObject->d3GetModuleConfigParam('_blEnableGa4')}]<span style="color: red">[{oxmultilang ident="D3INACTIVATEMOD"}]</span>[{/if}]
</label>
</div>
<div class="mb-3">
<div class="input-group w-50">
<span class="input-group-text" id="basic-addon3">[{oxmultilang ident="D3CONTAINERID"}]</span>
<input type="text" class="form-control" id="_sContainerID" name="editval[str][_sContainerID]" aria-describedby="basic-addon3" value="[{$d3ViewObject->d3GetModuleConfigParam('_sContainerID')}]">
</div>
<div class="text-muted">[{oxmultilang ident="D3CONTAINERID_HELP"}]</div>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="_blEnableDebug" name="editval[bool][_blEnableDebug]" [{if $d3ViewObject->d3GetModuleConfigParam('_blEnableDebug')}]checked[{/if}]>
<label class="form-check-label" for="flexCheckDefault">
[{oxmultilang ident="D3USEDEBUGMODE"}][{oxinputhelp ident="D3USEDEBUGMODE_HELP"}]
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="_blActivateConsentMode" name="editval[bool][_blEnableConsentMode]" [{if $d3ViewObject->d3GetModuleConfigParam('_blEnableConsentMode')}]checked[{/if}]>
<label class="form-check-label" for="flexCheckChecked">
[{oxmultilang ident="D3USEGOOGLECONSENTMODE"}][{oxinputhelp ident="D3USEGOOGLECONSENTMODE_HELP"}]
</label>
</div>
</div>
<button type="submit" name="save" class="btn btn-light" onClick="Javascript:document.d3gtmformedit.fnc.value='save'">[{oxmultilang ident="GENERAL_SAVE"}]</button>
</div>
</div>
<div class="col-6">
<div class="card border border-0">
<div class="accordion" id="accordionPanelsStayOpenExample">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#panelsStayOpen-cmpsettings" aria-expanded="true" aria-controls="panelsStayOpen-cmpsettings">
[{oxmultilang ident="D3CMPTABTITLE"}]
</button>
</h2>
<div id="panelsStayOpen-cmpsettings" class="accordion-collapse collapse show">
<div class="accordion-body">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="editval[bool][_blEnableOwnCookieManager]" value="" id="_hasOwnCookieManager" [{if $d3ViewObject->d3GetModuleConfigParam('_blEnableOwnCookieManager')}]checked[{/if}]>
<label class="form-check-label" for="flexCheckChecked">
[{oxmultilang ident="D3CMPUSEQ"}][{oxinputhelp ident="D3CMPUSEQ_HELP"}]
</label>
</div>
<div class="mb-3">
<label>
[{oxmultilang ident="D3CMP"}]
</label>
<select class="form-select w-50" name="editval[select][_HAS_STD_MANAGER]" aria-label="Default select example">
<option value="NONE" selected>[{oxmultilang ident="D3NONE"}]</option>
[{foreach from=$d3ManagerTypeArray key="sInternalName" item="sPublicName" name="editval[aCmpNameArray]"}]
<option value="[{$sInternalName}]" [{if $sInternalName === $d3CurrentCMP}]SELECTED[{/if}]>[{$sPublicName}]</option>
[{/foreach}]
</select>
</div>
<div>
<div class="input-group w-75">
<span class="input-group-text" id="basic-addon3">[{oxmultilang ident="D3CNTRLPARAM"}]</span>
<input type="text" class="form-control" id="_controlParameter" name="editval[str][_sControlParameter]" value="[{$d3ViewObject->d3GetModuleConfigParam('_sControlParameter')}]" aria-describedby="basic-addon3">
</div>
<div class="text-muted">[{oxmultilang ident="D3CNTRLPARAM_HELP"}]</div>
</div>
</div>
<button type="submit" name="save" class="btn btn-light w-100" onClick="Javascript:document.d3gtmformedit.fnc.value='save'">[{oxmultilang ident="GENERAL_SAVE"}]</button>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#panelsStayOpen-serversidetagging" aria-expanded="false" aria-controls="panelsStayOpen-serversidetagging">
[{oxmultilang ident="D3SERVERSIDETAGGING"}]
</button>
</h2>
<div id="panelsStayOpen-serversidetagging" class="accordion-collapse collapse">
<div class="accordion-body">
<div class="card bg-light rounded mb-3">
<div class="card-body">
[{oxmultilang ident="D3SERVERSIDETAGGING_HINT"}]
</div>
</div>
<div class="input-group mb-3">
<span class="input-group-text w-25" id="basic-addon3">[{oxmultilang ident="D3SERVERSIDETAGGING_TITLE_ACTIVE"}]</span>
<input type="text" class="form-control" id="_serversidetagging_js" name="editval[str][_sServersidetagging_js]" value="[{$d3ViewObject->d3GetModuleConfigParam('_sServersidetagging_js')}]" aria-describedby="basic-addon3">
</div>
<div class="input-group mb-3">
<span class="input-group-text w-25" id="basic-addon3">[{oxmultilang ident="D3SERVERSIDETAGGING_TITLE_PASSIVE"}]</span>
<input type="text" class="form-control" id="_serversidetagging_nojs" name="editval[str][_sServersidetagging_nojs]" value="[{$d3ViewObject->d3GetModuleConfigParam('_sServersidetagging_nojs')}]" aria-describedby="basic-addon3">
</div>
<div>
<button type="button" class="btn btn-light mt-3" data-bs-toggle="modal" data-bs-target="#exampleModal">
[{oxmultilang ident="D3DETAILED_DESC"}]
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<h4>[{oxmultilang ident="D3SERVERSIDETAGGING_TITLE_ACTIVE"}]</h4>
[{oxmultilang ident="D3SERVERSIDETAGGING_ACTIVE"}]
<hr>
<h4>[{oxmultilang ident="D3SERVERSIDETAGGING_TITLE_PASSIVE"}]</h4>
[{oxmultilang ident="D3SERVERSIDETAGGING_PASSIVE"}]
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">[{oxmultilang ident="D3CLOSE"}]</button>
</div>
</div>
</div>
</div>
</div>
</div>
<button type="submit" name="save" class="btn btn-light w-100" onClick="Javascript:document.d3gtmformedit.fnc.value='save'">[{oxmultilang ident="GENERAL_SAVE"}]</button>
</div>
</div>
[{if $d3ViewConfObject->d3IsUsercentricsCMPChosen()}]
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#panelsStayOpen-usercentricsdynamicoptions" aria-expanded="false" aria-controls="panelsStayOpen-usercentricsdynamicoptions">
[{oxmultilang ident="D3USRCNTRCSDYNOPT"}]
</button>
</h2>
<div id="panelsStayOpen-usercentricsdynamicoptions" class="accordion-collapse collapse">
<div class="accordion-body">
<div class="card bg-light rounded mb-3">
<div class="card-body">
<div class="text-danger mb-3">
[{oxmultilang ident="D3USRCNTRCSCFG_WARNING"}]
</div>
[{oxmultilang ident="D3USRCNTRCSCFG_DOCS"}]
</div>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="enabledefaultmeasurementvalues" name="editval[bool][_blEnableMeasurementCapabilities]" [{if $d3ViewObject->d3GetModuleConfigParam('_blEnableMeasurementCapabilities')}]checked[{/if}]>
<label class="form-check-label" for="flexCheckDefault">
[{oxmultilang ident="D3USRCNTRCSCFG_ACT_INDIVDEFVAL"}]
</label>
</div>
<div class="input-group mb-3">
<span class="input-group-text w-25" id="basic-addon3">[{oxmultilang ident="D3USRCNTRCSCFG_STD_CNST"}]</span>
<textarea name="editval[str][_sMeasurementCapabilities]" class="form-control" rows="15">[{$d3ViewObject->d3GetModuleConfigParam('_sDefaultMeasurementCapabilities')}]</textarea>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="enableUsercentricsConsentModeApi" name="editval[bool][_blEnableUsercentricsConsentModeApi]" [{if $d3ViewObject->d3GetModuleConfigParam('_blEnableUsercentricsConsentModeApi')}]checked[{/if}]>
<label class="form-check-label" for="flexCheckDefault">
[{oxmultilang ident="D3USRCNTRCSCFG_ACT_CNSTMDE_API"}]
</label>
</div>
<div class="input-group mb-3">
<span class="input-group-text w-25" id="basic-addon3">[{oxmultilang ident="D3USRCNTRCSCFG_CNSTMDE_API"}]</span>
<textarea name="editval[str][_sUsercentricsConsentModeApi]" class="form-control" rows="40">[{$d3ViewObject->d3GetModuleConfigParam('_sDefaultUsercentricsConsentModeApi')}]</textarea>
</div>
</div>
<button type="submit" name="save" class="btn btn-light w-100" onClick="Javascript:document.d3gtmformedit.fnc.value='save'">[{oxmultilang ident="GENERAL_SAVE"}]</button>
</div>
</div>
[{/if}]
</div>
</div>
</div>
</div>
</form>
</div>

View File

@ -1,11 +1,41 @@
[{* Always prepare the data layer to avoid errors *}]
<script>
var dataLayer = [{$oViewConf->getGtmDataLayer()}] || [];
</script>
[{if $oViewConf->isGA4enabled()}]
[{assign var="d3GtmContainerIdString" value=$oViewConf->getGtmContainerId()}]
<script>
var dataLayer = [{$oViewConf->getGtmDataLayer()}] || [];
</script>
[{/if}]
[{if $oViewConf->D3blShowGtmScript()}]
[{if $oViewConf->getGtmContainerId()}]
[{if $oViewConf->isGA4enabled() and $oViewConf->D3blShowGtmScript()}]
[{if $d3GtmContainerIdString}]
[{strip}]
[{if $oViewConf->isGtmConsentModeSetActivated()}]
<script type="text/javascript">
[{if $oViewConf->d3IsUsercentricsCMPChosen() and $oViewConf->d3GetModuleConfigParam('_blEnableMeasurementCapabilities')}]
[{$oViewConf->d3GetModuleConfigParam('_sMeasurementCapabilities')|strip}]
[{else}]
function gtag() {
dataLayer.push(arguments);
}
gtag("consent", "default", {
ad_user_data: "denied",
ad_personalization: "denied",
ad_storage: "denied",
analytics_storage: "denied",
wait_for_update: 2000
});
[{/if}]
</script>
[{/if}]
[{if $oViewConf->d3IsUsercentricsCMPChosen() and $oViewConf->d3GetModuleConfigParam('_blEnableUsercentricsConsentModeApi')}]
<script type="text/javascript">
[{$oViewConf->d3GetModuleConfigParam('_sUsercentricsConsentModeApi')|strip}]
</script>
[{/if}]
<!-- Google Tag Manager -->
<script [{$oViewConf->getGtmScriptAttributes()}]>
(function (w, d, s, l, i) {
@ -13,9 +43,9 @@
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;
j.src = '[{$oViewConf->getServerSidetaggingJsDomain()}]?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', '[{$oViewConf->getGtmContainerId()}]');
})(window, document, 'script', 'dataLayer', '[{$d3GtmContainerIdString}]');
</script>
<!-- End Google Tag Manager -->
[{/strip}]

View File

@ -2,7 +2,7 @@
[{if $oViewConf->getGtmContainerId()}][{strip}]
<!-- Google Tag Manager (noscript) -->
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=[{$oViewConf->getGtmContainerId()}]"
<iframe src="[{$oViewConf->getServerSidetaggingNoJsDomain()}]?id=[{$oViewConf->getGtmContainerId()}]"
height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<!-- End Google Tag Manager (noscript) -->

View File

@ -1,5 +1,5 @@
[{if $d3CmpBasket->getAddToBasketDecision() && $d3CmpBasket->d3GtmRequestedArticleLoadedByAnid() !== null}]
[{if $d3CmpBasket && $d3CmpBasket->getAddToBasketDecision() && $d3CmpBasket->d3GtmRequestedArticleLoadedByAnid() !== null}]
[{assign var="oGtmProduct" value=$d3CmpBasket->d3GtmRequestedArticleLoadedByAnid()}]
[{assign var="oGtmAmountArticlesAdded" value=$d3CmpBasket->getD3GtmAddToCartAmountArticles()}]
[{*$smarty.block.parent*}]

View File

@ -4,6 +4,69 @@ 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/GoogleAnalytics4/compare/2.17.2...rel_2.x) - 2024-x
## [2.19.0](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/2.18.2...2.19.0) - 2024-08-10
### Fixed
- usage of not yet existing function
## [2.18.2](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/2.18.1...2.18.2) - 2024-06-25
### Fixed
- oe-console apply-configuration triggers on-activate and overwrites existing values
## [2.18.1](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/2.18.0...2.18.1) - 2024-06-04
### Fixed
- missing return statement, on null/ none
## [2.18.0](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/2.17.2...2.18.0) - 2024-06-03
### Added
- trait for generalized method
- new admin UI
- additional check for properly activated module
- admin headitem alternative
- usercentrips step/ option 2
- group CMP-Functionalities/ properties into own Model
- additional help texts, translations, explanations
- extended docs
- auto safe on first approach ga4 + cmp-mod
- onActivate/ onDeactivate
## Changed
- declare module settings consistency
- configParamGetter
- clear dead code
- template code upgrade
- lang text
- amount of save-buttons
- Usercentrics-Class constants and adjust global-module-code to it
- CMP-output in tpl
- clear code and adjust Naming
## Fixed
- false class-property declaration
- wrong to-save param
## Removed
- deprecated and obsolete module-settings
- false composer xml-excludation
## [2.17.2](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/2.17.1...2.17.2) - 2024-04-11
### Fixed
- error on missing necessary-component
## [2.17.1](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/2.17.0...2.17.1) - 2024-04-10
### Fixed
- second call of getGtmContainerId() ( returned false )
## [2.17.0](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/2.16.0...2.17.0) - 2024-04-10
### Added
- Google-Analytics default values
- default values switch ( admin module settings )
- translations
## Changed
- centralized metadata-id
## [2.16.0](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/2.15.0...2.16.0) - 2024-03-20
### Added
- ( Google ) Server-Side tagging usability
## [2.15.0](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/2.14.0...2.15.0) - 2024-02-05
### Fixed
- missing Component-ArticleDetails extension, missing ManufacturerListController extension
@ -142,6 +205,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- using of ContainerFactory in ViewConfig
## [1.17.0](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/1.16.0...1.17.0) - 2024-04-11
### Added
- multilang translations
- GA4 consent-mode default values
### Changed
- metadataID centralized
## [1.16.0](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/1.15.1...1.16.0) - 2024-04-11
### Added
- ( Google ) Server-Side tagging usability
## [1.15.0](https://git.d3data.de/D3Public/GoogleAnalytics4/compare/1.14.0...1.15.0) - 2024-01-25
### Fixed
- missing Component-ArticleDetails extension, missing ManufacturerListController extension

View File

@ -5,6 +5,13 @@ Die Einbindung dieser Event-Templates erfolgt über TPL-Blöcke unter `source/mo
*Hinweis: nicht alle templates sind bereits gefüllt. Wünschen Sie die Implementierung eines unausgefüllten templates?
Kommen Sie auf uns zu unter https://www.d3data.de/
## Container-ID
Diese finden Sie im "Google-Tag-Manager"-Arbeitsbereich in der Navigationsleiste.
Sie beginnt mit GTM, gefolgt von einem Bindestrich und einer Zeichenkette.
Diese ID wird benötigt, um Google anzuweise, zu welchem "Google Tag Manager"-Arbeitsbereich die
gesammelten Daten im Daten-Stream geleitet werden sollen.
## Steuerungsparameter
Tragen Sie hier im Normalfall die ID des zu prüfenden Cookies ein.
In bestimmten Fällen, müssen Sie hier alternative Werte eintragen. Diese Fälle sind bedingt

View File

@ -4,41 +4,5 @@ namespace D3\GoogleAnalytics4\Modules\Application\Model;
class Category extends Category_parent
{
/**
* @param int $indexOfArray
* @return string
*/
public function getSplitCategoryArray(int $indexOfArray = -1, bool $bShallTakeStd = false) :string
{
if ($bShallTakeStd){
$splitCatArray =
array_values(
array_filter(
explode(
'/',
trim(
parse_url(
$this->getLink(),
5
)
)
)
)
);
if (($indexOfArray >= 0) and (false === empty($splitCatArray[$indexOfArray]))){
return $splitCatArray[$indexOfArray];
}else{
return "";
}
}
return
trim(
parse_url(
$this->getLink(),
5
)
);
}
use articleTreeStructure;
}

View File

@ -4,41 +4,5 @@ namespace D3\GoogleAnalytics4\Modules\Application\Model;
class Manufacturer extends Manufacturer_parent
{
/**
* @param int $indexOfArray
* @return string
*/
public function getSplitCategoryArray(int $indexOfArray = -1, bool $bShallTakeStd = false) :string
{
if ($bShallTakeStd){
$splitCatArray =
array_values(
array_filter(
explode(
'/',
trim(
parse_url(
$this->getLink(),
5
)
)
)
)
);
if (($indexOfArray >= 0) and (false === empty($splitCatArray[$indexOfArray]))){
return $splitCatArray[$indexOfArray];
}else{
return "";
}
}
return
trim(
parse_url(
$this->getLink(),
5
)
);
}
use articleTreeStructure;
}

View File

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace D3\GoogleAnalytics4\Modules\Application\Model;
class Vendor extends \OxidEsales\Eshop\Application\Model\Vendor
{
use articleTreeStructure;
}

View File

@ -0,0 +1,44 @@
<?php
namespace D3\GoogleAnalytics4\Modules\Application\Model;
trait articleTreeStructure
{
/**
* @param int $indexOfArray
* @return string
*/
public function getSplitCategoryArray(int $indexOfArray = -1, bool $bShallTakeStd = false) :string
{
if ($bShallTakeStd){
$splitCatArray =
array_values(
array_filter(
explode(
'/',
trim(
parse_url(
$this->getLink(),
5
)
)
)
)
);
if (($indexOfArray >= 0) and (false === empty($splitCatArray[$indexOfArray]))){
return $splitCatArray[$indexOfArray];
}else{
return "";
}
}
return
trim(
parse_url(
$this->getLink(),
5
)
);
}
}

View File

@ -12,6 +12,8 @@
namespace D3\GoogleAnalytics4\Modules\Core;
use D3\GoogleAnalytics4\Application\Model\CMP\Usercentrics;
use D3\GoogleAnalytics4\Application\Model\Constants;
use D3\GoogleAnalytics4\Application\Model\ManagerHandler;
use D3\GoogleAnalytics4\Application\Model\ManagerTypes;
use OxidEsales\Eshop\Application\Controller\FrontendController;
@ -28,16 +30,18 @@ class ViewConfig extends ViewConfig_parent
// Google Tag Manager Container ID
private $sContainerId = null;
private $sCookieManagerType = null;
// used CMP
private $sCookieManagerType = null;#
// isModule Activated properly?
private $blGA4enabled = null;
public function getGtmContainerId()
{
if ($this->sContainerId === null)
{
$this->sContainerId = ContainerFactory::getInstance()
->getContainer()
->get(ModuleSettingBridgeInterface::class)
->get('d3_gtm_sContainerID', 'd3googleanalytics4');
$this->sContainerId = $this->d3GetModuleConfigParam("_sContainerID");
}
return $this->sContainerId;
}
@ -59,7 +63,7 @@ class ViewConfig extends ViewConfig_parent
*/
public function shallUseOwnCookieManager() :bool
{
return (bool) Registry::getConfig()->getConfigParam('d3_gtm_settings_hasOwnCookieManager');
return (bool) $this->d3GetModuleConfigParam('_blEnableOwnCookieManager');
}
/**
@ -70,14 +74,18 @@ class ViewConfig extends ViewConfig_parent
/** @var Config $oConfig */
$oConfig = Registry::getConfig();
if (false === $this->isGA4enabled()){
return false;
}
// No Cookie Manager in use
if (!$this->shallUseOwnCookieManager()) {
if (false === $this->shallUseOwnCookieManager()) {
return true;
}
$this->defineCookieManagerType();
$sCookieID = trim($oConfig->getConfigParam('d3_gtm_settings_controlParameter'));
$sCookieID = trim($this->d3GetModuleConfigParam('_sControlParameter'));
// Netensio Cookie Manager
if ($this->sCookieManagerType === ManagerTypes::NET_COOKIE_MANAGER) {
@ -96,8 +104,8 @@ class ViewConfig extends ViewConfig_parent
// UserCentrics or consentmanager
if (
$this->sCookieManagerType === ManagerTypes::USERCENTRICS_MODULE
or $this->sCookieManagerType === ManagerTypes::USERCENTRICS_MANUALLY
$this->sCookieManagerType === Usercentrics::sModuleIncludationInternalName
or $this->sCookieManagerType === Usercentrics::sExternalIncludationInternalName
or $this->sCookieManagerType === ManagerTypes::CONSENTMANAGER
or $this->sCookieManagerType === ManagerTypes::COOKIEFIRST
or $this->sCookieManagerType === ManagerTypes::COOKIEBOT
@ -118,15 +126,15 @@ class ViewConfig extends ViewConfig_parent
*/
public function getGtmScriptAttributes() :string
{
$sControlParameter = trim(Registry::getConfig()->getConfigParam('d3_gtm_settings_controlParameter'));
$sControlParameter = trim($this->d3GetModuleConfigParam('_sControlParameter'));
if (false === $this->shallUseOwnCookieManager() or ($sControlParameter === '')){
return "";
}
if (
$this->sCookieManagerType === ManagerTypes::USERCENTRICS_MODULE
or $this->sCookieManagerType === ManagerTypes::USERCENTRICS_MANUALLY
$this->sCookieManagerType === Usercentrics::sModuleIncludationInternalName
or $this->sCookieManagerType === Usercentrics::sExternalIncludationInternalName
)
{
return 'data-usercentrics="' . $sControlParameter . '" type="text/plain" async=""';
@ -148,8 +156,6 @@ class ViewConfig extends ViewConfig_parent
return "";
}
private $blGA4enabled = null;
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
@ -158,15 +164,17 @@ class ViewConfig extends ViewConfig_parent
{
if ($this->blGA4enabled === null)
{
$this->sContainerId = ContainerFactory::getInstance()
->getContainer()
->get(ModuleSettingBridgeInterface::class)
->get('d3_gtm_blEnableGA4', 'd3googleanalytics4');
$this->blGA4enabled = $this->d3GetModuleConfigParam("_blEnableGA4");
}
return $this->blGA4enabled;
}
public function isGtmConsentModeSetActivated() :bool
{
return $this->d3GetModuleConfigParam("_blEnableConsentMode")?: false;
}
public function getGtmDataLayer()
{
if (!$this->getGtmContainerId()) return "[]";
@ -206,12 +214,47 @@ class ViewConfig extends ViewConfig_parent
public function isDebugModeOn() :bool
{
return Registry::getConfig()->getConfigParam('d3_gtm_blEnableDebug');
return $this->d3GetModuleConfigParam("_blEnableDebug")?: false;
}
public function isPromotionList($listId)
/**
* @return string
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function getServerSidetaggingJsDomain() :string
{
$oConfig = Registry::getConfig();
$aPromotionListIds = $oConfig->getConfigParam("") ?? ['bargainItems', 'newItems', 'topBox', 'alsoBought', 'accessories', 'cross'];
return $this->d3GetModuleConfigParam("_sServersidetagging_js")?: "";
}
/**
* @return string
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function getServerSidetaggingNoJsDomain() :string
{
return $this->d3GetModuleConfigParam('_sServersidetagging_nojs')?: "";
}
/**
* @param string $configParamName
* @return mixed
*/
public function d3GetModuleConfigParam(string $configParamName)
{
return Registry::getConfig()->getShopConfVar(Constants::OXID_MODULE_ID.$configParamName, null, Constants::OXID_MODULE_ID);
}
/**
* @return bool
*/
public function d3IsUsercentricsCMPChosen() :bool
{
$sCMPPubName = $this->d3GetModuleConfigParam('_HAS_STD_MANAGER');
$aPossibleCMP = (oxNew(ManagerTypes::class))->getManagerList();
return (bool) ($sCMPPubName === Usercentrics::sExternalIncludationInternalName
or $sCMPPubName === Usercentrics::sModuleIncludationInternalName);
}
}

44
Setup/Actions.php Normal file
View File

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace D3\GoogleAnalytics4\Setup;
use D3\GoogleAnalytics4\Application\Model\Constants;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\ViewConfig;
class Actions
{
/**
* @param string $sVarType
* @param string $sSettingName
* @param string $sSettingValue
* @return void
*/
public function d3SaveDefaultSettings(string $sVarType, string $sSettingName, string $sSettingValue){
$oConfig = Registry::getConfig();
if ($this->d3GetModuleConfigParam($sSettingName) and (trim($this->d3GetModuleConfigParam($sSettingName)) !== trim($sSettingValue))){
$sSettingValue = trim($this->d3GetModuleConfigParam($sSettingName));
}
$oConfig->saveShopConfVar(
$sVarType,
Constants::OXID_MODULE_ID.$sSettingName,
$sSettingValue,
$oConfig->getShopId(),
Constants::OXID_MODULE_ID
);
}
/**
* @param string $configParamName
* @return mixed
*/
public function d3GetModuleConfigParam(string $configParamName)
{
return Registry::getConfig()->getShopConfVar(Constants::OXID_MODULE_ID.$configParamName, null, Constants::OXID_MODULE_ID);
}
}

37
Setup/Events.php Normal file
View File

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace D3\GoogleAnalytics4\Setup;
class Events
{
/**
* @return void
*/
public static function onActivate()
{
$oActions = oxNew(Actions::class);
$oActions->d3SaveDefaultSettings(
'str',
'_sServersidetagging_js',
'https://www.googletagmanager.com/gtm.js'
);
$oActions->d3SaveDefaultSettings(
'str',
'_sServersidetagging_nojs',
'https://www.googletagmanager.com/ns.html'
);
$oActions->d3SaveDefaultSettings(
'str',
'_sContainerID',
'GTM-'
);
}
/**
* @return void
*/
public static function onDeactivate(){}
}

View File

@ -37,15 +37,14 @@
"*.md",
"composer.json",
".php-cs-fixer.php",
"*.xml",
"*.neon"
],
"target-directory": "d3/googleanalytics4"
}
},
"require": {
"php": ">=7.1",
"oxid-esales/oxideshop-ce": "^6.5",
"php": "7.1 - 8.2",
"oxid-esales/oxideshop-ce": "^6.5.3",
"google/apiclient":" ^2.0",
"phpstan/phpstan": "^1.10"
},

8
menu.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="ISO-8859-15"?>
<OX>
<OXMENU id="d3mxd3modules">
<MAINMENU id="d3mxgoogleanalytics4">
<SUBMENU id="d3mxgoogleanalytics4set" cl="d3googleanalytics4_main"/>
</MAINMENU>
</OXMENU>
</OX>

View File

@ -1,5 +1,7 @@
<?php
use D3\GoogleAnalytics4\Application\Controller\Admin\GA4AdminUserInterface_main as GA4AdminUserInterfaceMainController;
use D3\GoogleAnalytics4\Application\Model\Constants as Constants;
use D3\GoogleAnalytics4\Modules\Application\Component\d3GtmBasketComponentExtension;
use D3\GoogleAnalytics4\Modules\Application\Component\Widget\d3GtmWidgetArticleDetails as d3GtmWidgetArticleDetails;
use D3\GoogleAnalytics4\Modules\Application\Controller\ArticleDetailsController;
@ -35,7 +37,7 @@ use OxidEsales\Eshop\Core\ViewConfig as OEViewConfig;
$sMetadataVersion = '2.1';
$aModule = [
'id' => 'd3googleanalytics4',
'id' => Constants::OXID_MODULE_ID,
'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>
@ -48,10 +50,13 @@ $aModule = [
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' => '2.15.0',
'version' => '2.19.0',
'author' => 'Data Development (Inh.: Thomas Dartsch)',
'email' => 'support@shopmodule.com',
'url' => 'https://www.oxidmodule.com/',
'controllers' => [
'd3googleanalytics4_main' => GA4AdminUserInterfaceMainController::class
],
'extend' => [
// Core
OEViewConfig::class => ViewConfig::class,
@ -92,6 +97,10 @@ $aModule = [
'page/account/d3gtmnoticelist.tpl' => 'd3/googleanalytics4/Application/views/tpl/page/account/d3gtmnoticelist.tpl',
'page/account/d3gtmrecommendationlist.tpl' => 'd3/googleanalytics4/Application/views/tpl/page/account/d3gtmrecommendationlist.tpl',
'page/account/d3gtmwishlist.tpl' => 'd3/googleanalytics4/Application/views/tpl/page/account/d3gtmwishlist.tpl',
// Admin Templates
'ga4/admin/d3ga4uimain.tpl' => 'd3/googleanalytics4/Application/views/admin/tpl/d3googleanalytics4_main.tpl',
'ga4/admin/d3ga4uiheaditem.tpl' => 'd3/googleanalytics4/Application/views/admin/tpl/d3googleanalytics4_headitem.tpl',
],
'blocks' => [
// tag manager js
@ -167,48 +176,8 @@ $aModule = [
'position' => 150
]
],
'settings' => [
[
'group' => 'd3_gtm_settings',
'name' => 'd3_gtm_sContainerID',
'type' => 'str',
'value' => 'GTM-',
'position' => 0
],
[
'group' => 'd3_gtm_settings',
'name' => 'd3_gtm_blGA4enab',
'type' => 'bool',
'value' => true,
'position' => 1
],
[
'group' => 'd3_gtm_settings',
'name' => 'd3_gtm_blEnableDebug',
'type' => 'bool',
'value' => false,
'position' => 999
],
[
'group' => 'd3_gtm_settings_cookiemanager',
'name' => 'd3_gtm_settings_hasOwnCookieManager',
'type' => 'bool',
'value' => false,
'position' => 999
],
[
'group' => 'd3_gtm_settings_cookiemanager',
'name' => 'd3_gtm_settings_controlParameter',
'type' => 'str',
'value' => '',
'position' => 999
],
[
'group' => 'd3_gtm_settings_cookiemanager',
'name' => 'd3_gtm_settings_HAS_STD_MANAGER',
'type' => 'select',
'value' => 'none',
'constraints' => 'NONE|CONSENTMANAGER|USERCENTRICS|COOKIEFIRST|COOKIEBOT',
],
]
'events' => [
'onActivate' => '\D3\GoogleAnalytics4\Setup\Events::onActivate',
'onDeactivate' => '\D3\GoogleAnalytics4\Setup\Events::onDeactivate',
],
];