diff --git a/Config/Config.php b/Config/Config.php index d690c4e9..84245e72 100644 --- a/Config/Config.php +++ b/Config/Config.php @@ -235,6 +235,79 @@ public function isWebhookTriggerOnOrderState(): bool return $this->getWebhookTriggerMode() === 'on_order_state'; } + /** + * 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/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/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(), 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 0d579da1..9ef1094a 100644 --- a/Observer/TriggerPurchaseDataLayerEvent.php +++ b/Observer/TriggerPurchaseDataLayerEvent.php @@ -2,10 +2,12 @@ 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; 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; @@ -19,7 +21,7 @@ class TriggerPurchaseDataLayerEvent implements ObserverInterface public function __construct( CheckoutSessionDataProviderInterface $checkoutSessionDataProvider, PurchaseEvent $purchaseEvent, - Debugger $debugger + Debugger $debugger, ) { $this->checkoutSessionDataProvider = $checkoutSessionDataProvider; $this->purchaseEvent = $purchaseEvent; @@ -31,7 +33,6 @@ public function execute(Observer $observer) /** @var OrderInterface $order */ $order = $observer->getData('order'); - $this->debugger->debug("TriggerPurchaseDataLayerEvent::execute(): has changed "); $this->checkoutSessionDataProvider->add( 'purchase_event', $this->purchaseEvent->setOrder($order)->get() diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index b58f433d..db327fbc 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -84,6 +84,27 @@ on_order_state + + + + 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 + +
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 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) ?> +
+
+