From 0b39f6e7953cdc5027bb19b5916b3f00b3d41f22 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 23 Apr 2026 11:51:38 +0000 Subject: [PATCH] Introduce NewCustomerResolverInterface for new_customer data-layer field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `new_customer` value is emitted from three separate call sites (Purchase event, UserData order tag, and PurchaseWebhookEvent), each hardcoding `$order->getCustomerIsGuest()` as the heuristic. That leaves no single, upgrade-safe extension point for merchants who want a different definition (e.g. based on prior order count), and breaks for shops that convert guest orders into customer accounts on `sales_order_place_after` — isGuest() is false by the time the value is read. Extract the check into NewCustomerResolverInterface with a default IsGuestResolver implementation that preserves existing behavior. Merchants can now override the heuristic with a single DI preference. https://claude.ai/code/session_01KrUuLFtrNMyY2ZuwrvH8db --- Api/NewCustomerResolverInterface.php | 20 +++++++++++++++++++ DataLayer/Event/Purchase.php | 8 ++++++-- DataLayer/Event/PurchaseWebhookEvent.php | 8 ++++++-- DataLayer/Tag/Order/UserData.php | 8 ++++++-- Model/NewCustomerResolver/IsGuestResolver.php | 20 +++++++++++++++++++ etc/di.xml | 1 + 6 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 Api/NewCustomerResolverInterface.php create mode 100644 Model/NewCustomerResolver/IsGuestResolver.php diff --git a/Api/NewCustomerResolverInterface.php b/Api/NewCustomerResolverInterface.php new file mode 100644 index 00000000..320575ac --- /dev/null +++ b/Api/NewCustomerResolverInterface.php @@ -0,0 +1,20 @@ +orderItems = $orderItems; $this->config = $config; $this->priceFormatter = $priceFormatter; + $this->newCustomerResolver = $newCustomerResolver; } /** @@ -81,7 +85,7 @@ private function getUserData(OrderInterface $order): array 'email' => $order->getCustomerEmail() ?? '', 'first_name' => $order->getCustomerFirstname() ?? '', 'last_name' => $order->getCustomerLastname() ?? '', - 'new_customer' => $order->getCustomerIsGuest() ? 'true' : 'false' + 'new_customer' => $this->newCustomerResolver->isNewCustomer($order) ? 'true' : 'false' ]; } diff --git a/DataLayer/Event/PurchaseWebhookEvent.php b/DataLayer/Event/PurchaseWebhookEvent.php index cda540c3..a424c0e7 100644 --- a/DataLayer/Event/PurchaseWebhookEvent.php +++ b/DataLayer/Event/PurchaseWebhookEvent.php @@ -6,6 +6,7 @@ use Magento\Framework\HTTP\ClientFactory; use Magento\Framework\Serialize\Serializer\Json; +use Tagging\GTM\Api\NewCustomerResolverInterface; use Tagging\GTM\DataLayer\Tag\Order\OrderItems; use Magento\Sales\Api\Data\OrderInterface; use Tagging\GTM\Util\PriceFormatter; @@ -22,6 +23,7 @@ class PurchaseWebhookEvent private $priceFormatter; private LoggerInterface $logger; private Debugger $debugger; + private NewCustomerResolverInterface $newCustomerResolver; public function __construct( Json $json, @@ -30,7 +32,8 @@ public function __construct( Config $config, PriceFormatter $priceFormatter, LoggerInterface $logger, - Debugger $debugger + Debugger $debugger, + NewCustomerResolverInterface $newCustomerResolver ) { $this->json = $json; $this->clientFactory = $clientFactory; @@ -39,6 +42,7 @@ public function __construct( $this->priceFormatter = $priceFormatter; $this->logger = $logger; $this->debugger = $debugger; + $this->newCustomerResolver = $newCustomerResolver; } public function purchase(OrderInterface $order) @@ -122,7 +126,7 @@ public function purchase(OrderInterface $order) "email" => $order->getCustomerEmail() ?? '', "first_name" => $order->getCustomerFirstname() ?? '', "last_name" => $order->getCustomerLastname() ?? '', - "new_customer" => (string)($order->getCustomerIsGuest() ? "true" : "false") + "new_customer" => (string)($this->newCustomerResolver->isNewCustomer($order) ? "true" : "false") ]; } catch (\Exception $e) { $this->debugger->debug($e->getMessage()); diff --git a/DataLayer/Tag/Order/UserData.php b/DataLayer/Tag/Order/UserData.php index 9f624336..068f6345 100644 --- a/DataLayer/Tag/Order/UserData.php +++ b/DataLayer/Tag/Order/UserData.php @@ -8,18 +8,22 @@ use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderRepositoryInterface; use Tagging\GTM\Api\Data\TagInterface; +use Tagging\GTM\Api\NewCustomerResolverInterface; class UserData implements TagInterface { private CheckoutSession $checkoutSession; private OrderRepositoryInterface $orderRepository; + private NewCustomerResolverInterface $newCustomerResolver; public function __construct( CheckoutSession $checkoutSession, - OrderRepositoryInterface $orderRepository + OrderRepositoryInterface $orderRepository, + NewCustomerResolverInterface $newCustomerResolver ) { $this->checkoutSession = $checkoutSession; $this->orderRepository = $orderRepository; + $this->newCustomerResolver = $newCustomerResolver; } /** @@ -54,7 +58,7 @@ public function get(): array 'email' => $order->getCustomerEmail() ?? '', 'first_name' => $order->getCustomerFirstname() ?? '', 'last_name' => $order->getCustomerLastname() ?? '', - 'new_customer' => $order->getCustomerIsGuest() ? 'true' : 'false' + 'new_customer' => $this->newCustomerResolver->isNewCustomer($order) ? 'true' : 'false' ]; } diff --git a/Model/NewCustomerResolver/IsGuestResolver.php b/Model/NewCustomerResolver/IsGuestResolver.php new file mode 100644 index 00000000..1b1c0ede --- /dev/null +++ b/Model/NewCustomerResolver/IsGuestResolver.php @@ -0,0 +1,20 @@ +getCustomerIsGuest(); + } +} diff --git a/etc/di.xml b/etc/di.xml index 8995bbc0..3392c8da 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -2,6 +2,7 @@ +