From ce12f3caf06baae4cb71f3d5cfd924cea33250b7 Mon Sep 17 00:00:00 2001 From: Victor Kloeppel Date: Wed, 3 Dec 2025 16:32:01 +0100 Subject: [PATCH 1/8] first commit --- Config/Config.php | 10 +++ Observer/TriggerPurchaseDataLayerEvent.php | 73 +++++++++++++++++++++- etc/adminhtml/system.xml | 9 +++ 3 files changed, 90 insertions(+), 2 deletions(-) diff --git a/Config/Config.php b/Config/Config.php index d690c4e9..a6ca6aee 100644 --- a/Config/Config.php +++ b/Config/Config.php @@ -235,6 +235,16 @@ public function isWebhookTriggerOnOrderState(): bool return $this->getWebhookTriggerMode() === 'on_order_state'; } + /** + * Check if purchase event should only trigger on paid orders + * + * @return bool + */ + public function isPurchaseEventPaymentCheckEnabled(): bool + { + return (bool)$this->getModuleConfigValueAdvanced('purchase_event_payment_check', false); + } + /** * @return bool */ diff --git a/Observer/TriggerPurchaseDataLayerEvent.php b/Observer/TriggerPurchaseDataLayerEvent.php index 0d579da1..cf5146dc 100644 --- a/Observer/TriggerPurchaseDataLayerEvent.php +++ b/Observer/TriggerPurchaseDataLayerEvent.php @@ -6,6 +6,7 @@ use Magento\Framework\Event\ObserverInterface; use Magento\Sales\Api\Data\OrderInterface; use Tagging\GTM\Api\CheckoutSessionDataProviderInterface; +use Tagging\GTM\Config\Config; use Tagging\GTM\DataLayer\Event\Purchase as PurchaseEvent; use Tagging\GTM\Logger\Debugger; use Exception; @@ -15,15 +16,18 @@ class TriggerPurchaseDataLayerEvent implements ObserverInterface private CheckoutSessionDataProviderInterface $checkoutSessionDataProvider; private PurchaseEvent $purchaseEvent; private Debugger $debugger; + private Config $config; public function __construct( CheckoutSessionDataProviderInterface $checkoutSessionDataProvider, PurchaseEvent $purchaseEvent, - Debugger $debugger + Debugger $debugger, + Config $config ) { $this->checkoutSessionDataProvider = $checkoutSessionDataProvider; $this->purchaseEvent = $purchaseEvent; $this->debugger = $debugger; + $this->config = $config; } public function execute(Observer $observer) @@ -31,10 +35,75 @@ public function execute(Observer $observer) /** @var OrderInterface $order */ $order = $observer->getData('order'); - $this->debugger->debug("TriggerPurchaseDataLayerEvent::execute(): has changed "); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Purchase event triggered'); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_id: ' . $order->getId()); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_increment_id: ' . $order->getIncrementId()); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_status: ' . $order->getStatus()); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_state: ' . $order->getState()); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_grand_total: ' . $order->getGrandTotal()); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_total_paid: ' . $order->getTotalPaid()); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_total_due: ' . $order->getTotalDue()); + + // Check if payment check is enabled + $paymentCheckEnabled = $this->config->isPurchaseEventPaymentCheckEnabled(); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): payment_check_enabled: ' . ($paymentCheckEnabled ? 'true' : 'false')); + + if ($paymentCheckEnabled) { + if (!$this->shouldTriggerPurchaseEvent($order)) { + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Payment check failed - order is not fully paid, skipping purchase event'); + return; + } + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Payment check passed - order is fully paid, sending purchase event'); + } else { + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Payment check disabled - sending purchase event without payment verification'); + } + $this->checkoutSessionDataProvider->add( 'purchase_event', $this->purchaseEvent->setOrder($order)->get() ); + + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Purchase event added to checkout session'); + } + + /** + * Check if purchase event should be triggered based on payment status + * + * @param OrderInterface $order + * @return bool + */ + private function shouldTriggerPurchaseEvent(OrderInterface $order): bool + { + $grandTotal = (float)$order->getGrandTotal(); + $totalPaid = (float)$order->getTotalPaid(); + $tolerance = 0.01; // Tolerance for floating point comparison + + $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): grand_total: ' . $grandTotal); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): total_paid: ' . $totalPaid); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): difference: ' . abs($grandTotal - $totalPaid)); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): tolerance: ' . $tolerance); + + // Check if order is fully paid (with tolerance) + $isFullyPaid = abs($grandTotal - $totalPaid) <= $tolerance; + + if ($isFullyPaid) { + $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): Order is fully paid'); + + // Additional check: order should be in a paid state + $paidStates = ['processing', 'complete']; + $orderState = $order->getState(); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): order_state: ' . $orderState); + + if (in_array($orderState, $paidStates)) { + $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): Order state is in paid states, purchase event will be sent'); + return true; + } else { + $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): Order state is not in paid states, but order is fully paid - purchase event will be sent'); + return true; + } + } + + $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): Order is not fully paid, purchase event will not be sent'); + return false; } } diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index b58f433d..d25d1219 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -84,6 +84,15 @@ on_order_state + + + + Note: For asynchronous payment methods, the purchase event may be sent after the customer leaves the success page.]]> + Magento\Config\Model\Config\Source\Yesno + + 1 + + From 74b2473e835ea6bf1ad3a28c9350c9d85413f9ac Mon Sep 17 00:00:00 2001 From: Victor Kloeppel Date: Thu, 4 Dec 2025 14:13:01 +0100 Subject: [PATCH 2/8] added extra logging --- Observer/TriggerPurchaseDataLayerEvent.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Observer/TriggerPurchaseDataLayerEvent.php b/Observer/TriggerPurchaseDataLayerEvent.php index cf5146dc..d743d4a4 100644 --- a/Observer/TriggerPurchaseDataLayerEvent.php +++ b/Observer/TriggerPurchaseDataLayerEvent.php @@ -2,6 +2,7 @@ namespace Tagging\GTM\Observer; +use Magento\Framework\App\RequestInterface; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Sales\Api\Data\OrderInterface; @@ -17,17 +18,20 @@ class TriggerPurchaseDataLayerEvent implements ObserverInterface private PurchaseEvent $purchaseEvent; private Debugger $debugger; private Config $config; + private RequestInterface $request; public function __construct( CheckoutSessionDataProviderInterface $checkoutSessionDataProvider, PurchaseEvent $purchaseEvent, Debugger $debugger, - Config $config + Config $config, + RequestInterface $request ) { $this->checkoutSessionDataProvider = $checkoutSessionDataProvider; $this->purchaseEvent = $purchaseEvent; $this->debugger = $debugger; $this->config = $config; + $this->request = $request; } public function execute(Observer $observer) @@ -35,7 +39,19 @@ public function execute(Observer $observer) /** @var OrderInterface $order */ $order = $observer->getData('order'); + // Get page information + $fullActionName = $this->request->getFullActionName(); + $requestUri = $this->request->getRequestUri(); + $moduleName = $this->request->getModuleName(); + $controllerName = $this->request->getControllerName(); + $actionName = $this->request->getActionName(); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Purchase event triggered'); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_full_action_name: ' . $fullActionName); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_module: ' . $moduleName); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_controller: ' . $controllerName); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_action: ' . $actionName); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_request_uri: ' . $requestUri); $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_id: ' . $order->getId()); $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_increment_id: ' . $order->getIncrementId()); $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_status: ' . $order->getStatus()); From 93aa724be737a441f26a4297ac7e0134382b42cb Mon Sep 17 00:00:00 2001 From: Victor Kloeppel Date: Thu, 4 Dec 2025 15:14:10 +0100 Subject: [PATCH 3/8] some extra changes --- Config/Config.php | 73 ++++++++++++++++++++++ Model/Config/Source/CheckoutActions.php | 61 ++++++++++++++++++ Observer/TriggerPurchaseDataLayerEvent.php | 40 ++++++++++++ etc/adminhtml/system.xml | 21 +++++++ 4 files changed, 195 insertions(+) create mode 100644 Model/Config/Source/CheckoutActions.php diff --git a/Config/Config.php b/Config/Config.php index a6ca6aee..9209875b 100644 --- a/Config/Config.php +++ b/Config/Config.php @@ -245,6 +245,79 @@ public function isPurchaseEventPaymentCheckEnabled(): bool return (bool)$this->getModuleConfigValueAdvanced('purchase_event_payment_check', false); } + /** + * Check if page-specific checking is enabled for purchase event + * + * @return bool + */ + public function isPurchaseEventPageCheckEnabled(): bool + { + return (bool)$this->getModuleConfigValueAdvanced('purchase_event_page_check_enabled', true); + } + + /** + * Get allowed checkout actions for purchase event + * + * @return array + */ + public function getPurchaseEventAllowedCheckoutActions(): array + { + // Only return actions if page check is enabled + if (!$this->isPurchaseEventPageCheckEnabled()) { + return []; + } + + $configValue = $this->getModuleConfigValueAdvanced('purchase_event_allowed_checkout_actions', null); + + // If null or empty and page check is enabled, return all available actions as default + if ($configValue === null || $configValue === '' || $configValue === false) { + return $this->getAllAvailableCheckoutActions(); + } + + // Multiselect values in Magento can be stored in different formats: + // 1. As an array (when retrieved via ScopeConfigInterface in some cases) + // 2. As a comma-separated string (most common) + // 3. As a JSON string (less common) + + if (is_array($configValue)) { + $actions = array_filter(array_map('trim', $configValue)); + // If array is empty, return all available actions + return empty($actions) ? $this->getAllAvailableCheckoutActions() : $actions; + } + + if (is_string($configValue)) { + // Try JSON decode first (in case it's stored as JSON) + $decoded = json_decode($configValue, true); + if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) { + $actions = array_filter(array_map('trim', $decoded)); + return empty($actions) ? $this->getAllAvailableCheckoutActions() : $actions; + } + + // Otherwise treat as comma-separated string + $actions = array_filter(array_map('trim', explode(',', $configValue))); + return empty($actions) ? $this->getAllAvailableCheckoutActions() : $actions; + } + + return $this->getAllAvailableCheckoutActions(); + } + + /** + * Get all available checkout actions + * + * @return array + */ + private function getAllAvailableCheckoutActions(): array + { + return [ + 'checkout_index_index', + 'checkout_onepage_success', + 'checkout_cart_index', + 'checkout_onepage_index', + 'checkout_multishipping_index', + 'checkout_multishipping_success', + ]; + } + /** * @return bool */ diff --git a/Model/Config/Source/CheckoutActions.php b/Model/Config/Source/CheckoutActions.php new file mode 100644 index 00000000..2c8ef1a5 --- /dev/null +++ b/Model/Config/Source/CheckoutActions.php @@ -0,0 +1,61 @@ + 'Checkout Index (Main checkout page)', + 'checkout_onepage_success' => 'Checkout Success Page', + 'checkout_cart_index' => 'Shopping Cart Page', + 'checkout_onepage_index' => 'One Page Checkout', + 'checkout_multishipping_index' => 'Multishipping Checkout', + 'checkout_multishipping_success' => 'Multishipping Success', + ]; + + /** + * {@inheritdoc} + */ + public function toOptionArray(): array + { + $options = []; + + foreach (self::CHECKOUT_ACTIONS as $value => $label) { + $options[] = [ + 'value' => $value, + 'label' => __($label) + ]; + } + + return $options; + } + + /** + * Get all available checkout action values + * + * @return array + */ + public function getAvailableActions(): array + { + return array_keys(self::CHECKOUT_ACTIONS); + } + + /** + * Get default checkout actions (for fallback) + * + * @return array + */ + public function getDefaultActions(): array + { + return [ + 'checkout_index_index', + 'checkout_onepage_success', + ]; + } +} + diff --git a/Observer/TriggerPurchaseDataLayerEvent.php b/Observer/TriggerPurchaseDataLayerEvent.php index d743d4a4..7a6d5149 100644 --- a/Observer/TriggerPurchaseDataLayerEvent.php +++ b/Observer/TriggerPurchaseDataLayerEvent.php @@ -60,6 +60,21 @@ public function execute(Observer $observer) $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_total_paid: ' . $order->getTotalPaid()); $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_total_due: ' . $order->getTotalDue()); + // Check if page-specific checking is enabled + $pageCheckEnabled = $this->config->isPurchaseEventPageCheckEnabled(); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_check_enabled: ' . ($pageCheckEnabled ? 'true' : 'false')); + + // If page check is enabled, validate we're on an allowed checkout page + if ($pageCheckEnabled) { + if (!$this->isCheckoutPage()) { + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Not on an allowed checkout page, skipping purchase event'); + return; + } + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): On allowed checkout page, proceeding with purchase event'); + } else { + $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Page check disabled - purchase event will fire from any page'); + } + // Check if payment check is enabled $paymentCheckEnabled = $this->config->isPurchaseEventPaymentCheckEnabled(); $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): payment_check_enabled: ' . ($paymentCheckEnabled ? 'true' : 'false')); @@ -122,4 +137,29 @@ private function shouldTriggerPurchaseEvent(OrderInterface $order): bool $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): Order is not fully paid, purchase event will not be sent'); return false; } + + /** + * Check if the current request is on a checkout page + * + * @return bool + */ + private function isCheckoutPage(): bool + { + $fullActionName = $this->request->getFullActionName(); + $moduleName = $this->request->getModuleName(); + + // Check if we're in the checkout module + if ($moduleName !== 'checkout') { + return false; + } + + // Get allowed checkout actions from configuration + // This will return all available actions if none are configured (default behavior) + $allowedActions = $this->config->getPurchaseEventAllowedCheckoutActions(); + + $this->debugger->debug('TriggerPurchaseDataLayerEvent::isCheckoutPage(): Allowed actions: ' . implode(', ', $allowedActions)); + $this->debugger->debug('TriggerPurchaseDataLayerEvent::isCheckoutPage(): Current action: ' . $fullActionName); + + return in_array($fullActionName, $allowedActions, true); + } } diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index d25d1219..71063ab6 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -93,6 +93,27 @@ 1 + + + + Default: Enabled (all checkout pages are selected by default)
+ If disabled: Purchase event will fire from any page where an order is placed (admin, API, etc.)]]>
+ Magento\Config\Model\Config\Source\Yesno + + 1 + +
+ + + + Default: All checkout pages are enabled when page check is turned on
+ Note: If page check is disabled, these selections are ignored and the event fires from any page.]]>
+ Tagging\GTM\Model\Config\Source\CheckoutActions + + 1 + 1 + +
From c555954adb42027730b4805d10a1d5759bfffc9c Mon Sep 17 00:00:00 2001 From: Victor Kloeppel Date: Thu, 4 Dec 2025 15:33:34 +0100 Subject: [PATCH 4/8] cleaned code --- Config/Config.php | 10 --- Observer/TriggerPurchaseDataLayerEvent.php | 82 ---------------------- etc/adminhtml/system.xml | 9 --- 3 files changed, 101 deletions(-) diff --git a/Config/Config.php b/Config/Config.php index 9209875b..84245e72 100644 --- a/Config/Config.php +++ b/Config/Config.php @@ -235,16 +235,6 @@ public function isWebhookTriggerOnOrderState(): bool return $this->getWebhookTriggerMode() === 'on_order_state'; } - /** - * Check if purchase event should only trigger on paid orders - * - * @return bool - */ - public function isPurchaseEventPaymentCheckEnabled(): bool - { - return (bool)$this->getModuleConfigValueAdvanced('purchase_event_payment_check', false); - } - /** * Check if page-specific checking is enabled for purchase event * diff --git a/Observer/TriggerPurchaseDataLayerEvent.php b/Observer/TriggerPurchaseDataLayerEvent.php index 7a6d5149..3f1946c3 100644 --- a/Observer/TriggerPurchaseDataLayerEvent.php +++ b/Observer/TriggerPurchaseDataLayerEvent.php @@ -39,32 +39,9 @@ public function execute(Observer $observer) /** @var OrderInterface $order */ $order = $observer->getData('order'); - // Get page information - $fullActionName = $this->request->getFullActionName(); - $requestUri = $this->request->getRequestUri(); - $moduleName = $this->request->getModuleName(); - $controllerName = $this->request->getControllerName(); - $actionName = $this->request->getActionName(); - - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Purchase event triggered'); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_full_action_name: ' . $fullActionName); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_module: ' . $moduleName); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_controller: ' . $controllerName); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_action: ' . $actionName); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_request_uri: ' . $requestUri); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_id: ' . $order->getId()); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_increment_id: ' . $order->getIncrementId()); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_status: ' . $order->getStatus()); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_state: ' . $order->getState()); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_grand_total: ' . $order->getGrandTotal()); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_total_paid: ' . $order->getTotalPaid()); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): order_total_due: ' . $order->getTotalDue()); - - // Check if page-specific checking is enabled $pageCheckEnabled = $this->config->isPurchaseEventPageCheckEnabled(); $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_check_enabled: ' . ($pageCheckEnabled ? 'true' : 'false')); - // If page check is enabled, validate we're on an allowed checkout page if ($pageCheckEnabled) { if (!$this->isCheckoutPage()) { $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Not on an allowed checkout page, skipping purchase event'); @@ -75,67 +52,10 @@ public function execute(Observer $observer) $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Page check disabled - purchase event will fire from any page'); } - // Check if payment check is enabled - $paymentCheckEnabled = $this->config->isPurchaseEventPaymentCheckEnabled(); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): payment_check_enabled: ' . ($paymentCheckEnabled ? 'true' : 'false')); - - if ($paymentCheckEnabled) { - if (!$this->shouldTriggerPurchaseEvent($order)) { - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Payment check failed - order is not fully paid, skipping purchase event'); - return; - } - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Payment check passed - order is fully paid, sending purchase event'); - } else { - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Payment check disabled - sending purchase event without payment verification'); - } - $this->checkoutSessionDataProvider->add( 'purchase_event', $this->purchaseEvent->setOrder($order)->get() ); - - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Purchase event added to checkout session'); - } - - /** - * Check if purchase event should be triggered based on payment status - * - * @param OrderInterface $order - * @return bool - */ - private function shouldTriggerPurchaseEvent(OrderInterface $order): bool - { - $grandTotal = (float)$order->getGrandTotal(); - $totalPaid = (float)$order->getTotalPaid(); - $tolerance = 0.01; // Tolerance for floating point comparison - - $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): grand_total: ' . $grandTotal); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): total_paid: ' . $totalPaid); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): difference: ' . abs($grandTotal - $totalPaid)); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): tolerance: ' . $tolerance); - - // Check if order is fully paid (with tolerance) - $isFullyPaid = abs($grandTotal - $totalPaid) <= $tolerance; - - if ($isFullyPaid) { - $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): Order is fully paid'); - - // Additional check: order should be in a paid state - $paidStates = ['processing', 'complete']; - $orderState = $order->getState(); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): order_state: ' . $orderState); - - if (in_array($orderState, $paidStates)) { - $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): Order state is in paid states, purchase event will be sent'); - return true; - } else { - $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): Order state is not in paid states, but order is fully paid - purchase event will be sent'); - return true; - } - } - - $this->debugger->debug('TriggerPurchaseDataLayerEvent::shouldTriggerPurchaseEvent(): Order is not fully paid, purchase event will not be sent'); - return false; } /** @@ -153,8 +73,6 @@ private function isCheckoutPage(): bool return false; } - // Get allowed checkout actions from configuration - // This will return all available actions if none are configured (default behavior) $allowedActions = $this->config->getPurchaseEventAllowedCheckoutActions(); $this->debugger->debug('TriggerPurchaseDataLayerEvent::isCheckoutPage(): Allowed actions: ' . implode(', ', $allowedActions)); diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 71063ab6..db327fbc 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -84,15 +84,6 @@ on_order_state - - - - Note: For asynchronous payment methods, the purchase event may be sent after the customer leaves the success page.]]> - Magento\Config\Model\Config\Source\Yesno - - 1 - - From d5c607627738996100b8941c3eab04fd1495c255 Mon Sep 17 00:00:00 2001 From: Victor Kloeppel Date: Fri, 5 Dec 2025 09:51:38 +0100 Subject: [PATCH 5/8] debug settings --- view/frontend/layout/default.xml | 5 ++++ view/frontend/layout/hyva_default.xml | 5 ++++ .../templates/hyva/debug-action.phtml | 24 +++++++++++++++++++ .../templates/luma/debug-action.phtml | 23 ++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 view/frontend/templates/hyva/debug-action.phtml create mode 100644 view/frontend/templates/luma/debug-action.phtml diff --git a/view/frontend/layout/default.xml b/view/frontend/layout/default.xml index e3bea9d4..3075ac6b 100644 --- a/view/frontend/layout/default.xml +++ b/view/frontend/layout/default.xml @@ -32,6 +32,11 @@ + + get(\Magento\Framework\App\RequestInterface::class); +$fullActionName = $request->getFullActionName(); +$moduleName = $request->getModuleName(); +$controllerName = $request->getControllerName(); +$actionName = $request->getActionName(); +?> +
+ Current Action Debug:
+ Full Action: escapeHtml($fullActionName) ?>
+ Module: escapeHtml($moduleName) ?> | + Controller: escapeHtml($controllerName) ?> | + Action: escapeHtml($actionName) ?> +
+
+registerInlineScript() ?> + diff --git a/view/frontend/templates/luma/debug-action.phtml b/view/frontend/templates/luma/debug-action.phtml new file mode 100644 index 00000000..31bf4543 --- /dev/null +++ b/view/frontend/templates/luma/debug-action.phtml @@ -0,0 +1,23 @@ +get(\Magento\Framework\App\RequestInterface::class); +$fullActionName = $request->getFullActionName(); +$moduleName = $request->getModuleName(); +$controllerName = $request->getControllerName(); +$actionName = $request->getActionName(); +?> +
+ Current Action Debug:
+ Full Action: escapeHtml($fullActionName) ?>
+ Module: escapeHtml($moduleName) ?> | + Controller: escapeHtml($controllerName) ?> | + Action: escapeHtml($actionName) ?> +
+
+ From 76d9dbea7f67f754d479cb2e0b196e0494950dd1 Mon Sep 17 00:00:00 2001 From: Victor Kloeppel Date: Fri, 5 Dec 2025 10:15:57 +0100 Subject: [PATCH 6/8] cleaned code and added logging --- CustomerData/GtmCheckout.php | 98 +++++++++++++++++++++- Observer/TriggerPurchaseDataLayerEvent.php | 42 ---------- 2 files changed, 96 insertions(+), 44 deletions(-) diff --git a/CustomerData/GtmCheckout.php b/CustomerData/GtmCheckout.php index 77952f8d..68b20f28 100644 --- a/CustomerData/GtmCheckout.php +++ b/CustomerData/GtmCheckout.php @@ -3,19 +3,29 @@ namespace Tagging\GTM\CustomerData; use Magento\Customer\CustomerData\SectionSourceInterface; +use Magento\Framework\App\RequestInterface; use Tagging\GTM\Api\CheckoutSessionDataProviderInterface; +use Tagging\GTM\Config\Config; class GtmCheckout implements SectionSourceInterface { private CheckoutSessionDataProviderInterface $checkoutSessionDataProvider; + private RequestInterface $request; + private Config $config; /** * @param CheckoutSessionDataProviderInterface $checkoutSessionDataProvider + * @param RequestInterface $request + * @param Config $config */ public function __construct( - CheckoutSessionDataProviderInterface $checkoutSessionDataProvider + CheckoutSessionDataProviderInterface $checkoutSessionDataProvider, + RequestInterface $request, + Config $config ) { $this->checkoutSessionDataProvider = $checkoutSessionDataProvider; + $this->request = $request; + $this->config = $config; } /** @@ -23,8 +33,92 @@ public function __construct( */ public function getSectionData(): array { + // Add debug logging: the action, module, enabled status + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] getSectionData called'); + } $gtmEvents = $this->checkoutSessionDataProvider->get(); + + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] Current GTM events: ' . json_encode($gtmEvents)); + } + + $pageCheckEnabled = $this->config->isPurchaseEventPageCheckEnabled(); + + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] PurchaseEventPageCheckEnabled = ' . ($pageCheckEnabled ? 'true' : 'false')); + } + + if (!$pageCheckEnabled) { + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] PageCheck DISABLED, returning all GTM events'); + } + return ['gtm_events' => $gtmEvents]; + } + $isCheckoutPage = $this->isCheckoutPage(); + + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] isCheckoutPage = ' . ($isCheckoutPage ? 'true' : 'false')); + } + + if ($isCheckoutPage) { + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] On checkout page: clearing all checkout session GTM events'); + } + $this->checkoutSessionDataProvider->clear(); + return ['gtm_events' => $gtmEvents]; + } + + $purchaseEvent = $gtmEvents['purchase_event'] ?? null; + $otherEvents = $gtmEvents; + unset($otherEvents['purchase_event']); + + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] Not checkout page, will keep only non-purchase_event events: ' . json_encode($otherEvents)); + } + $this->checkoutSessionDataProvider->clear(); - return ['gtm_events' => $gtmEvents]; + + if ($purchaseEvent !== null) { + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] purchase_event found, re-adding it to checkout session data'); + } + $this->checkoutSessionDataProvider->add('purchase_event', $purchaseEvent); + } + + return ['gtm_events' => $otherEvents]; + + } + + private function isCheckoutPage(): bool + { + $fullActionName = $this->request->getFullActionName(); + $moduleName = $this->request->getModuleName(); + + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] Checking if is checkout page, module=' . $moduleName . ' fullAction=' . $fullActionName); + } + + if ($moduleName !== 'checkout') { + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] Not checkout module, skipping'); + } + return false; + } + + $allowedActions = $this->config->getPurchaseEventAllowedCheckoutActions(); + + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] Allowed actions: ' . implode(', ', $allowedActions)); + $this->debugger->debug('[GtmCheckout] Current fullActionName: ' . $fullActionName); + } + + $isAllowed = in_array($fullActionName, $allowedActions, true); + + if (property_exists($this, 'debugger') && $this->debugger) { + $this->debugger->debug('[GtmCheckout] isCheckoutPage returning: ' . ($isAllowed ? 'true' : 'false')); + } + + return $isAllowed; } } diff --git a/Observer/TriggerPurchaseDataLayerEvent.php b/Observer/TriggerPurchaseDataLayerEvent.php index 3f1946c3..9ef1094a 100644 --- a/Observer/TriggerPurchaseDataLayerEvent.php +++ b/Observer/TriggerPurchaseDataLayerEvent.php @@ -17,21 +17,15 @@ class TriggerPurchaseDataLayerEvent implements ObserverInterface private CheckoutSessionDataProviderInterface $checkoutSessionDataProvider; private PurchaseEvent $purchaseEvent; private Debugger $debugger; - private Config $config; - private RequestInterface $request; public function __construct( CheckoutSessionDataProviderInterface $checkoutSessionDataProvider, PurchaseEvent $purchaseEvent, Debugger $debugger, - Config $config, - RequestInterface $request ) { $this->checkoutSessionDataProvider = $checkoutSessionDataProvider; $this->purchaseEvent = $purchaseEvent; $this->debugger = $debugger; - $this->config = $config; - $this->request = $request; } public function execute(Observer $observer) @@ -39,45 +33,9 @@ public function execute(Observer $observer) /** @var OrderInterface $order */ $order = $observer->getData('order'); - $pageCheckEnabled = $this->config->isPurchaseEventPageCheckEnabled(); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): page_check_enabled: ' . ($pageCheckEnabled ? 'true' : 'false')); - - if ($pageCheckEnabled) { - if (!$this->isCheckoutPage()) { - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Not on an allowed checkout page, skipping purchase event'); - return; - } - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): On allowed checkout page, proceeding with purchase event'); - } else { - $this->debugger->debug('TriggerPurchaseDataLayerEvent::execute(): Page check disabled - purchase event will fire from any page'); - } - $this->checkoutSessionDataProvider->add( 'purchase_event', $this->purchaseEvent->setOrder($order)->get() ); } - - /** - * Check if the current request is on a checkout page - * - * @return bool - */ - private function isCheckoutPage(): bool - { - $fullActionName = $this->request->getFullActionName(); - $moduleName = $this->request->getModuleName(); - - // Check if we're in the checkout module - if ($moduleName !== 'checkout') { - return false; - } - - $allowedActions = $this->config->getPurchaseEventAllowedCheckoutActions(); - - $this->debugger->debug('TriggerPurchaseDataLayerEvent::isCheckoutPage(): Allowed actions: ' . implode(', ', $allowedActions)); - $this->debugger->debug('TriggerPurchaseDataLayerEvent::isCheckoutPage(): Current action: ' . $fullActionName); - - return in_array($fullActionName, $allowedActions, true); - } } From 377c4de057e93ba0646fb8c9ad56f6f77b8d9fc3 Mon Sep 17 00:00:00 2001 From: Victor Kloeppel Date: Fri, 5 Dec 2025 11:16:32 +0100 Subject: [PATCH 7/8] changed name --- view/frontend/layout/checkout_onepage_success.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/frontend/layout/checkout_onepage_success.xml b/view/frontend/layout/checkout_onepage_success.xml index 9536bbcb..2525a69b 100644 --- a/view/frontend/layout/checkout_onepage_success.xml +++ b/view/frontend/layout/checkout_onepage_success.xml @@ -19,7 +19,7 @@ - trytagging_purchase + trytagging_purchase2 Tagging\GTM\DataLayer\Tag\Order\Order Tagging\GTM\DataLayer\Tag\Order\OrderItems From 70000e850f3ba952400d9a6992e735e09f9151eb Mon Sep 17 00:00:00 2001 From: Victor Kloeppel Date: Fri, 5 Dec 2025 11:19:56 +0100 Subject: [PATCH 8/8] changed names --- DataLayer/Event/Purchase.php | 2 +- DataLayer/Event/PurchaseWebhookEvent.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DataLayer/Event/Purchase.php b/DataLayer/Event/Purchase.php index 078aee32..120aa8e3 100644 --- a/DataLayer/Event/Purchase.php +++ b/DataLayer/Event/Purchase.php @@ -32,7 +32,7 @@ public function get(): array { $order = $this->order; return [ - 'event' => 'trytagging_purchase', + 'event' => 'trytagging_purchase3', 'ecommerce' => [ 'transaction_id' => $order->getIncrementId(), 'affiliation' => $this->config->getStoreName(), diff --git a/DataLayer/Event/PurchaseWebhookEvent.php b/DataLayer/Event/PurchaseWebhookEvent.php index cda540c3..1f1e7e43 100644 --- a/DataLayer/Event/PurchaseWebhookEvent.php +++ b/DataLayer/Event/PurchaseWebhookEvent.php @@ -82,7 +82,7 @@ public function purchase(OrderInterface $order) } $data = [ - 'event' => 'trytagging_purchase', + 'event' => 'trytagging_purchase4', 'marketing' => $marketingData, 'store_domain' => $this->config->getStoreDomain(), 'plugin_version' => $this->config->getVersion(),