Skip to content

Commit

Permalink
Merge pull request #187 from stefandoorn/view-item-list
Browse files Browse the repository at this point in the history
Add support for 'view_item_list'
  • Loading branch information
stefandoorn authored Jun 15, 2023
2 parents fe315c6 + 5cf1a77 commit bb6893e
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
1 change: 1 addition & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
68 changes: 68 additions & 0 deletions src/EventListener/ViewItemListListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

declare(strict_types=1);

namespace StefanDoorn\SyliusGtmEnhancedEcommercePlugin\EventListener;

use StefanDoorn\SyliusGtmEnhancedEcommercePlugin\Helper\MainRequest;
use StefanDoorn\SyliusGtmEnhancedEcommercePlugin\TagManager\ViewItemListInterface;
use Sylius\Component\Core\Model\TaxonInterface;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Sylius\Component\Taxonomy\Repository\TaxonRepositoryInterface;
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use Symfony\Component\HttpKernel\Event\ControllerEvent;

final class ViewItemListListener
{
private TaxonRepositoryInterface $taxonRepository;

private LocaleContextInterface $localeContext;

private FirewallMap $firewallMap;

private ViewItemListInterface $viewItemList;

public function __construct(
TaxonRepositoryInterface $taxonRepository,
LocaleContextInterface $localeContext,
FirewallMap $firewallMap,
ViewItemListInterface $viewItemList
) {
$this->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'));
}
}
15 changes: 15 additions & 0 deletions src/Resources/config/features/view_item_list.yml
Original file line number Diff line number Diff line change
@@ -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 }
12 changes: 12 additions & 0 deletions src/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
124 changes: 124 additions & 0 deletions src/TagManager/ViewItemList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?php

declare(strict_types=1);

namespace StefanDoorn\SyliusGtmEnhancedEcommercePlugin\TagManager;

use Doctrine\Common\Collections\ArrayCollection;
use StefanDoorn\SyliusGtmEnhancedEcommercePlugin\Helper\GoogleImplementationEnabled;
use StefanDoorn\SyliusGtmEnhancedEcommercePlugin\Helper\ProductIdentifierHelper;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Core\Calculator\ProductVariantPriceCalculatorInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\TaxonInterface;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Sylius\Component\Product\Resolver\ProductVariantResolverInterface;
use Xynnn\GoogleTagManagerBundle\Service\GoogleTagManagerInterface;

final class ViewItemList implements ViewItemListInterface
{
private GoogleTagManagerInterface $googleTagManager;

private ProductRepositoryInterface $productRepository;

private ChannelContextInterface $channelContext;

private LocaleContextInterface $localeContext;

private ProductIdentifierHelper $productIdentifierHelper;

private ProductVariantResolverInterface $productVariantResolver;

private ProductVariantPriceCalculatorInterface $productVariantPriceCalculator;

private GoogleImplementationEnabled $googleImplementationEnabled;

public function __construct(
GoogleTagManagerInterface $googleTagManager,
ProductRepositoryInterface $productRepository,
ChannelContextInterface $channelContext,
LocaleContextInterface $localeContext,
ProductIdentifierHelper $productIdentifierHelper,
ProductVariantResolverInterface $productVariantResolver,
ProductVariantPriceCalculatorInterface $productVariantPriceCalculator,
GoogleImplementationEnabled $googleImplementationEnabled
) {
$this->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),
]);
}
}
12 changes: 12 additions & 0 deletions src/TagManager/ViewItemListInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace StefanDoorn\SyliusGtmEnhancedEcommercePlugin\TagManager;

use Sylius\Component\Core\Model\TaxonInterface;

interface ViewItemListInterface
{
public function add(TaxonInterface $taxon, ?string $listId = null): void;
}

0 comments on commit bb6893e

Please sign in to comment.