vendor/pimcore/pimcore/bundles/EcommerceFrameworkBundle/Tracking/Tracker/Piwik.php line 243

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4.  * Pimcore
  5.  *
  6.  * This source file is available under two different licenses:
  7.  * - GNU General Public License version 3 (GPLv3)
  8.  * - Pimcore Enterprise License (PEL)
  9.  * Full copyright and license information is available in
  10.  * LICENSE.md which is distributed with this source code.
  11.  *
  12.  * @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  13.  * @license    http://www.pimcore.org/license     GPLv3 and PEL
  14.  */
  15. namespace Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\Tracker;
  16. use Pimcore\Analytics\Piwik\Tracker as PiwikTracker;
  17. use Pimcore\Bundle\EcommerceFrameworkBundle\CartManager\CartInterface;
  18. use Pimcore\Bundle\EcommerceFrameworkBundle\Model\AbstractOrder;
  19. use Pimcore\Bundle\EcommerceFrameworkBundle\Model\ProductInterface;
  20. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\CartProductActionAddInterface;
  21. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\CartProductActionRemoveInterface;
  22. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\CartUpdateInterface;
  23. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\CategoryPageViewInterface;
  24. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\CheckoutCompleteInterface;
  25. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\ProductAction;
  26. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\ProductViewInterface;
  27. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\Tracker;
  28. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\TrackEventInterface;
  29. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\TrackingCodeAwareInterface;
  30. use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\TrackingItemBuilderInterface;
  31. use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
  32. use Symfony\Component\OptionsResolver\OptionsResolver;
  33. class Piwik extends Tracker implements
  34.     ProductViewInterface,
  35.     CategoryPageViewInterface,
  36.     CartUpdateInterface,
  37.     CartProductActionAddInterface,
  38.     CartProductActionRemoveInterface,
  39.     CheckoutCompleteInterface,
  40.     TrackEventInterface,
  41.     TrackingCodeAwareInterface
  42. {
  43.     /**
  44.      * @var PiwikTracker
  45.      */
  46.     private $tracker;
  47.     /**
  48.      * @var bool
  49.      */
  50.     private $handleCartAdd true;
  51.     /**
  52.      * @var bool
  53.      */
  54.     private $handleCartRemove true;
  55.     /**
  56.      * @var string[]
  57.      */
  58.     protected $trackedCodes = [];
  59.     public function __construct(
  60.         PiwikTracker $tracker,
  61.         TrackingItemBuilderInterface $trackingItemBuilder,
  62.         EngineInterface $templatingEngine,
  63.         array $options = []
  64.     ) {
  65.         $this->tracker $tracker;
  66.         parent::__construct($trackingItemBuilder$templatingEngine$options);
  67.     }
  68.     protected function configureOptions(OptionsResolver $resolver)
  69.     {
  70.         parent::configureOptions($resolver);
  71.         $resolver->setDefaults([
  72.             'template_prefix' => 'PimcoreEcommerceFrameworkBundle:Tracking/piwik',
  73.             // by default, a cart add/remove delegates to cart update
  74.             // if you manually trigger cart update on every change you can
  75.             // can set this to false to avoid handling of add/remove
  76.             'handle_cart_add' => true,
  77.             'handle_cart_remove' => true,
  78.         ]);
  79.         $resolver->setAllowedTypes('handle_cart_add''bool');
  80.         $resolver->setAllowedTypes('handle_cart_remove''bool');
  81.     }
  82.     protected function processOptions(array $options)
  83.     {
  84.         parent::processOptions($options);
  85.         $this->handleCartAdd $options['handle_cart_add'];
  86.         $this->handleCartRemove $options['handle_cart_remove'];
  87.     }
  88.     /**
  89.      * @inheritDoc
  90.      */
  91.     public function trackProductView(ProductInterface $product)
  92.     {
  93.         $item $this->trackingItemBuilder->buildProductViewItem($product);
  94.         $call = [
  95.             'setEcommerceView',
  96.             $item->getId(),
  97.             $item->getName(),
  98.         ];
  99.         $call[] = $this->filterCategories($item->getCategories());
  100.         $price $item->getPrice();
  101.         if (!empty($price)) {
  102.             $call[] = $price;
  103.         }
  104.         $result $this->renderCalls([$call]);
  105.         $this->trackCode($result);
  106.     }
  107.     /**
  108.      * @inheritDoc
  109.      */
  110.     public function trackCategoryPageView($category$page null)
  111.     {
  112.         $category $this->filterCategories($category);
  113.         $result $this->renderCalls([
  114.             [
  115.                 'setEcommerceView',
  116.                 false,
  117.                 false,
  118.                 $category,
  119.             ],
  120.         ]);
  121.         $this->trackCode($result);
  122.     }
  123.     /**
  124.      * @inheritDoc
  125.      */
  126.     public function trackCartProductActionAdd(CartInterface $cartProductInterface $product$quantity 1)
  127.     {
  128.         if ($this->handleCartAdd) {
  129.             $this->trackCartUpdate($cart);
  130.         }
  131.     }
  132.     /**
  133.      * @inheritDoc
  134.      */
  135.     public function trackCartProductActionRemove(CartInterface $cartProductInterface $product$quantity 1)
  136.     {
  137.         if ($this->handleCartRemove) {
  138.             $this->trackCartUpdate($cart);
  139.         }
  140.     }
  141.     /**
  142.      * @inheritDoc
  143.      */
  144.     public function trackCartUpdate(CartInterface $cart)
  145.     {
  146.         $items $this->trackingItemBuilder->buildCheckoutItemsByCart($cart);
  147.         $calls $this->buildItemCalls($items);
  148.         $calls[] = [
  149.             'trackEcommerceCartUpdate',
  150.             $cart->getPriceCalculator()->getGrandTotal()->getAmount()->asNumeric(),
  151.         ];
  152.         $result $this->renderCalls($calls);
  153.         $this->trackCode($result);
  154.     }
  155.     /**
  156.      * @inheritDoc
  157.      */
  158.     public function trackCheckoutComplete(AbstractOrder $order)
  159.     {
  160.         $items $this->trackingItemBuilder->buildCheckoutItems($order);
  161.         $transaction $this->trackingItemBuilder->buildCheckoutTransaction($order);
  162.         $calls $this->buildItemCalls($items);
  163.         $calls[] = [
  164.             'trackEcommerceOrder',
  165.             $transaction->getId(),
  166.             $transaction->getTotal(),
  167.             $transaction->getSubTotal(),
  168.             $transaction->getTax(),
  169.             $transaction->getShipping(),
  170.         ];
  171.         $result $this->renderCalls($calls);
  172.         $this->trackCode($result);
  173.     }
  174.     public function trackEvent(
  175.         string $eventCategory,
  176.         string $eventAction,
  177.         string $eventLabel null,
  178.         int $eventValue null
  179.     ) {
  180.         $result $this->renderCalls([
  181.             [
  182.                 'trackEvent',
  183.                 $eventCategory,
  184.                 $eventAction,
  185.                 $eventLabel,
  186.                 $eventValue,
  187.             ],
  188.         ]);
  189.         $this->trackCode($result);
  190.     }
  191.     public function getTrackedCodes(): array
  192.     {
  193.         return $this->trackedCodes;
  194.     }
  195.     public function trackCode(string $code)
  196.     {
  197.         $this->trackedCodes[] = $code;
  198.         $this->tracker->addCodePart($codePiwikTracker::BLOCK_BEFORE_TRACK);
  199.     }
  200.     private function renderCalls(array $calls): string
  201.     {
  202.         return $this->renderTemplate('calls', [
  203.             'calls' => $calls,
  204.         ]);
  205.     }
  206.     /**
  207.      * @param ProductAction[] $items
  208.      *
  209.      * @return array
  210.      */
  211.     private function buildItemCalls(array $items): array
  212.     {
  213.         $calls = [];
  214.         foreach ($items as $item) {
  215.             $calls[] = [
  216.                 'addEcommerceItem',
  217.                 $item->getId(),
  218.                 $item->getName(),
  219.                 $item->getCategories(),
  220.                 $item->getPrice(),
  221.                 $item->getQuantity(),
  222.             ];
  223.         }
  224.         return $calls;
  225.     }
  226.     private function filterCategories($categoriesint $limit 5)
  227.     {
  228.         if (null === $categories) {
  229.             return $categories;
  230.         }
  231.         $result null;
  232.         if (is_array($categories)) {
  233.             // add max 5 categories
  234.             $categories array_slice($categories05);
  235.             $result = [];
  236.             foreach ($categories as $category) {
  237.                 $category trim((string)$category);
  238.                 if (!empty($category)) {
  239.                     $result[] = $category;
  240.                 }
  241.             }
  242.             $result array_slice($result0$limit);
  243.         } else {
  244.             $result trim((string)$categories);
  245.         }
  246.         if (!empty($result)) {
  247.             return $result;
  248.         }
  249.     }
  250. }