diff --git a/README.md b/README.md index 632a657..76e8a39 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,8 @@ References + examples of how to set-up your GTM container: https://developers.go Supported events: +* `view_item` +* `view_item_list` * `add_to_cart` * `remove_from_cart` * `view_cart` diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index e6cb2d3..0b0b701 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -39,6 +39,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->booleanNode('product_clicks')->defaultTrue()->end() ->booleanNode('cart')->defaultTrue()->end() ->booleanNode('view_item')->defaultTrue()->end() + ->booleanNode('view_item_list')->defaultTrue()->end() ->arrayNode('checkout') ->canBeDisabled() ->addDefaultsIfNotSet() diff --git a/src/EventListener/ViewItemListListener.php b/src/EventListener/ViewItemListListener.php new file mode 100644 index 0000000..cd5e1ac --- /dev/null +++ b/src/EventListener/ViewItemListListener.php @@ -0,0 +1,68 @@ +taxonRepository = $taxonRepository; + $this->localeContext = $localeContext; + $this->firewallMap = $firewallMap; + $this->viewItemList = $viewItemList; + } + + public function __invoke(ControllerEvent $event): void + { + if (!MainRequest::isMainRequest($event)) { + return; + } + + $request = $event->getRequest(); + + $firewallConfig = $this->firewallMap->getFirewallConfig($request); + if (null !== $firewallConfig && 'shop' !== $firewallConfig->getName()) { + return; + } + + if ('sylius_shop_product_index' !== $request->get('_route')) { + return; + } + + $slug = $request->get('slug', null); + + if (null === $slug) { + return; + } + + $taxon = $this->taxonRepository->findOneBySlug($slug, $this->localeContext->getLocaleCode()); + + if (!$taxon instanceof TaxonInterface) { + return; + } + + $this->viewItemList->add($taxon, $request->get('_route')); + } +} diff --git a/src/Resources/config/features/view_item_list.yml b/src/Resources/config/features/view_item_list.yml new file mode 100644 index 0000000..e08a745 --- /dev/null +++ b/src/Resources/config/features/view_item_list.yml @@ -0,0 +1,15 @@ +services: + _defaults: + autowire: false + autoconfigure: false + public: false + + sylius.google_tag_manager.enhanced_ecommerce_tracking.view_item_list.listener: + class: StefanDoorn\SyliusGtmEnhancedEcommercePlugin\EventListener\ViewItemListListener + arguments: + - "@sylius.repository.taxon" + - "@sylius.context.locale" + - "@security.firewall.map" + - "@sylius.google_tag_manager.enhanced_ecommerce_tracking.tag_manager.view_item_list" + tags: + - { name: kernel.event_listener, event: kernel.controller } diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml index ff9c8b5..70293b6 100644 --- a/src/Resources/config/services.yml +++ b/src/Resources/config/services.yml @@ -30,6 +30,18 @@ services: - "@sylius.calculator.product_variant_price" - "@sylius.google_tag_manager.enhanced_ecommerce.tracking.google_implementation_enabled" + sylius.google_tag_manager.enhanced_ecommerce_tracking.tag_manager.view_item_list: + class: StefanDoorn\SyliusGtmEnhancedEcommercePlugin\TagManager\ViewItemList + arguments: + - "@google_tag_manager" + - "@sylius.repository.product" + - "@sylius.context.channel" + - "@sylius.context.locale" + - "@sylius.google_tag_manager.enhanced_ecommerce_tracking.helper.product_identifier" + - "@sylius.product_variant_resolver.default" + - "@sylius.calculator.product_variant_price" + - "@sylius.google_tag_manager.enhanced_ecommerce.tracking.google_implementation_enabled" + sylius.google_tag_manager.enhanced_ecommerce_tracking.tag_manager.checkout_step: class: StefanDoorn\SyliusGtmEnhancedEcommercePlugin\TagManager\CheckoutStep arguments: diff --git a/src/TagManager/ViewItemList.php b/src/TagManager/ViewItemList.php new file mode 100644 index 0000000..4be8cbb --- /dev/null +++ b/src/TagManager/ViewItemList.php @@ -0,0 +1,124 @@ +googleTagManager = $googleTagManager; + $this->productRepository = $productRepository; + $this->channelContext = $channelContext; + $this->localeContext = $localeContext; + $this->productIdentifierHelper = $productIdentifierHelper; + $this->productVariantResolver = $productVariantResolver; + $this->productVariantPriceCalculator = $productVariantPriceCalculator; + $this->googleImplementationEnabled = $googleImplementationEnabled; + } + + public function add(TaxonInterface $taxon, ?string $listId = null): void + { + if (!$this->googleImplementationEnabled->isGA4Enabled()) { + return; + } + + $this->addViewItemListData($taxon, $listId); + } + + private function addViewItemListData(TaxonInterface $taxon, ?string $listId = null): void + { + $products = new ArrayCollection( + $this->productRepository->createShopListQueryBuilder( + $this->channelContext->getChannel(), + $taxon, + $this->localeContext->getLocaleCode(), + [], + false, + )->getQuery()->getResult() + ); + + if (0 === $products->count()) { + return; + } + + $index = 0; + $taxonName = null !== $taxon ? $taxon->getName() : ''; + + $data = [ + 'item_list_id' => $listId, + 'item_list_name' => $taxon->getName(), + 'items' => $products->map(function (ProductInterface $product) use ($taxonName, &$index): array { + $productData = [ + 'item_id' => $this->productIdentifierHelper->getProductIdentifier($product), + 'item_name' => $product->getName(), + 'affiliation' => $this->channelContext->getChannel()->getName(), + 'item_category' => $taxonName, + 'index' => $index++, + ]; + + $productVariant = $this->productVariantResolver->getVariant($product); + + if (null !== $productVariant) { + $productVariantPrice = $this->productVariantPriceCalculator->calculate( + $productVariant, + [ + 'channel' => $this->channelContext->getChannel(), + ] + ); + + $productData['price'] = $productVariantPrice / 100; + } + + return $productData; + })->toArray(), + ]; + + // https://developers.google.com/analytics/devguides/collection/ga4/ecommerce?client_type=gtm#view_item_details + $this->googleTagManager->addPush([ + 'ecommerce' => null, + ]); + + $this->googleTagManager->addPush([ + 'event' => 'view_item_list', + 'ecommerce' => \array_filter($data), + ]); + } +} diff --git a/src/TagManager/ViewItemListInterface.php b/src/TagManager/ViewItemListInterface.php new file mode 100644 index 0000000..6cd6f9a --- /dev/null +++ b/src/TagManager/ViewItemListInterface.php @@ -0,0 +1,12 @@ +