src/Twig/GoogleTagManagerExtension.php line 365

Open in your IDE?
  1. <?php
  2. namespace App\Twig;
  3. use App\Entity\Main\Cart;
  4. use App\Entity\Main\DiscountCode;
  5. use App\Entity\Main\Pack;
  6. use App\Entity\Main\PackProduct;
  7. use App\Entity\Main\Product;
  8. use App\Entity\Main\Tracking;
  9. use App\Entity\Main\TransactionInvoice;
  10. use App\Entity\Main\TransactionInvoiceItem;
  11. use App\Entity\Main\TransactionInvoicePack;
  12. use App\Entity\Main\User;
  13. use App\EventListener\Main\UtmTrackingListener;
  14. use App\Services\CartManager;
  15. use App\Services\PackManager;
  16. use App\Services\TrackingManager;
  17. use App\Services\ABTestManager;
  18. use App\Services\DiscountCodeManager;
  19. use App\Services\SiteManager;
  20. use Psr\Log\LoggerInterface;
  21. use Symfony\Component\HttpFoundation\RequestStack;
  22. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  23. use Twig\Extension\AbstractExtension;
  24. use Twig\TwigFunction;
  25. class GoogleTagManagerExtension extends AbstractExtension
  26. {
  27.     const
  28.         GTM_SESSION_LOGIN_EVENT_KEY 'gtm_login_event_to_fire',
  29.         GTM_SESSION_PROMOCODE_EVENT_KEY 'gtm_promocode_event_to_fire',
  30.         GTM_SESSION_PROMOCODE_NAME_KEY 'gtm_promocode_name',
  31.         GTM_SESSION_PAYMENT_ERROR_EVENT_KEY 'gtm_payment_error_event_to_fire',
  32.         GTM_SESSION_PAYMENT_3DS_SWAP_EVENT_KEY 'gtm_payment_error_event_to_fire',
  33.         GTM_SESSION_PAYMENT_3DS_ERROR_EVENT_KEY 'gtm_payment_error_event_to_fire'
  34.     ;
  35.     const
  36.         GTM_TYPE_GA4 'GA4',
  37.         GTM_TYPE_UA 'UA',
  38.         FORCE_DISPLAY_TEXT 'data_cmp_ab=1',
  39.         FORCE_DISPLAY_SUB_TEXT 'data_cmp_ab=2'
  40.     ;
  41.     const
  42.         GTM_UA_CURRENCY_KEY 'currencyCode',
  43.         GTM_UA_PRODUCTS_KEY 'products',
  44.         GTM_UA_PRODUCT_ID_KEY 'id',
  45.         GTM_UA_PRODUCT_NAME_KEY 'name',
  46.         GTM_UA_PURCHASE_REVENUE_KEY 'revenue',
  47.         GTM_UA_PURCHASE_REVENUE_NOT_VAT_KEY 'revenue_not_vat',
  48.         GTM_UA_PURCHASE_ID_KEY 'id',
  49.         GTM_GA4_CURRENCY_KEY 'currency',
  50.         GTM_GA4_PRODUCTS_KEY 'items',
  51.         GTM_GA4_PRODUCT_ID_KEY 'item_id',
  52.         GTM_GA4_PRODUCT_NAME_KEY 'item_name',
  53.         GTM_GA4_PURCHASE_REVENUE_KEY 'value',
  54.         GTM_GA4_PURCHASE_REVENUE_NOT_VAT_KEY 'value_not_vat',
  55.         GTM_GA4_PURCHASE_ID_KEY 'transaction_id'
  56.     ;
  57.     protected $environment;
  58.     protected $googleHeadTag = <<<TAG
  59. <!-- Google Tag Manager -->
  60. <script __*FORCEDISPLAY*__>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
  61. new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
  62. j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
  63. 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
  64. })(window,document,'script','dataLayer','__*GTMTAG*__');</script>
  65. <!-- End Google Tag Manager -->
  66. TAG;
  67.     protected $googleBodyTag = <<<TAG
  68. <!-- Google Tag Manager (noscript) -->
  69. <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=__*GTMTAG*__"
  70. height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  71. <!-- End Google Tag Manager (noscript) -->
  72. TAG;
  73.     // checkout step is depending on the page visited by the user.
  74.     // 0 => no cart
  75.     // 1 => cart with products inside
  76.     // 2 => shipping page is reached.
  77.     // 3 => payment page is reached
  78.     // 4 => purchase is successful.
  79.     // 99 => confirming double order
  80.     protected $steps = [
  81.         'brulafine_show_packs' => 1,
  82.         'brulafine_updateCustomPack' => 1,
  83.         'brulafine_cart' => 1,
  84.         'brulafine_confirm' => 99,
  85.         'brulafine_push_check_pack_switch' => 2,
  86.         'brulafine_updateCart' => 2,
  87.         'brulafine_discount' => 2,
  88.         'brulafine_shipping' => 2,
  89.         'brulafine_commande' => 2,
  90.         'brulafine_payment' => 3,
  91.         'brulafine_over' => 4
  92.     ];
  93.     /**
  94.      * @var SiteManager
  95.      */
  96.     private $siteManager;
  97.     /**
  98.      * @var ABTestManager
  99.      */
  100.     private $ABTestManager;
  101.     /**
  102.      * @var TrackingManager
  103.      */
  104.     private $trackingFactory;
  105.     /**
  106.      * @var CartManager
  107.      */
  108.     private $cartFactory;
  109.     private $gtmEnabled;
  110.     private $gtmTagId;
  111.     private $session;
  112.     /**
  113.      * @var RequestStack
  114.      */
  115.     private $requestStack;
  116.     /**
  117.      * @var TokenStorageInterface
  118.      */
  119.     private $tokenStorage;
  120.     private $cart 0;
  121.     private $tracking 0;
  122.     /**
  123.      * @var PackManager
  124.      */
  125.     private $packFactory;
  126.     /**
  127.      * @var LoggerInterface
  128.      */
  129.     private $logger;
  130.     private $googleTagManagerVersion;
  131.     /**
  132.      * @var mixed
  133.      */
  134.     private $brandName;
  135.     /**
  136.      * @var DiscountCodeManager
  137.      */
  138.     private DiscountCodeManager $discountCodeManager;
  139.     /**
  140.      * @var mixed
  141.      */
  142.     private $siteName;
  143.     private string $locale;
  144.     /**
  145.      * GoogleTagManagerExtension constructor.
  146.      * @param $environment
  147.      * @param TrackingManager $trackingFactory
  148.      * @param SiteManager $siteManager
  149.      * @param ABTestManager $ABTestManager
  150.      * @param CartManager $cartFactory
  151.      * @param RequestStack $requestStack
  152.      * @param TokenStorageInterface $tokenStorage
  153.      * @param $gtmEnabled
  154.      * @param $gtmTagId
  155.      * @param PackManager $packFactory
  156.      * @param LoggerInterface $logger
  157.      * @param DiscountCodeManager $discountCodeManager
  158.      */
  159.     public function __construct(
  160.         $environment,
  161.         TrackingManager $trackingFactory,
  162.         SiteManager $siteManager,
  163.         ABTestManager $ABTestManager,
  164.         CartManager $cartFactory,
  165.         RequestStack $requestStack,
  166.         TokenStorageInterface $tokenStorage,
  167.         $gtmEnabled,
  168.         $gtmTagId,
  169.         PackManager $packFactory,
  170.         LoggerInterface $logger,
  171.         DiscountCodeManager $discountCodeManager
  172.     ) {
  173.         $this->environment $environment;
  174.         $this->siteManager $siteManager;
  175.         $this->ABTestManager $ABTestManager;
  176.         $this->trackingFactory $trackingFactory;
  177.         $this->cartFactory $cartFactory;
  178.         $this->gtmEnabled $gtmEnabled;
  179.         $this->gtmTagId $gtmTagId;
  180.         $this->requestStack $requestStack;
  181.         $this->tokenStorage $tokenStorage;
  182.         $this->packFactory $packFactory;
  183.         $this->logger $logger;
  184.         $this->googleTagManagerVersion $this->siteManager->getYamlConfigParameter('google_tag_manager_version');
  185.         $this->brandName $this->siteManager->getYamlConfigParameter('brandName');
  186.         $this->siteName $this->siteManager->getYamlConfigParameter('websiteName');
  187.         $this->discountCodeManager $discountCodeManager;
  188.         if ($this->requestStack->getCurrentRequest()) {
  189.             $this->session $this->requestStack->getCurrentRequest()->getSession();
  190.             $this->locale $this->requestStack->getCurrentRequest()->getLocale();
  191.         }
  192.     }
  193.     /**
  194.      * @return array|TwigFunction[]
  195.      */
  196.     public function getFunctions(): array
  197.     {
  198.         return [
  199.             new TwigFunction('getGTMHeadTag', [$this'getGTMHeadTag'], ['is_safe' => ['html']]),
  200.             new TwigFunction('getGTMBodyTag', [$this'getGTMBodyTag'], ['is_safe' => ['html']]),
  201.             new TwigFunction('getGTMLayerTag', [$this'getGTMLayerTag'], ['is_safe' => ['html']]),
  202.             new TwigFunction('getGTMEvents', [$this'getGTMEvents'], ['is_safe' => ['html']]),
  203.         ];
  204.     }
  205.     /**
  206.      * @return mixed
  207.      */
  208.     public function getGTMHeadTag($forceLoading true)
  209.     {
  210.         if (!$this->gtmEnabled) {
  211.             return '';
  212.         }
  213.         if (!isset($this->gtmTagId[$this->locale])) {
  214.             return '';
  215.         }
  216.         $tag str_replace("__*GTMTAG*__"$this->gtmTagId[$this->locale], $this->googleHeadTag);
  217.         $forcedDisplay '';
  218.         if ($forceLoading) {
  219.             $forcedDisplay self::FORCE_DISPLAY_TEXT;
  220.         }
  221.         $tag str_replace("__*FORCEDISPLAY*__"$forcedDisplay$tag);
  222.         return $tag;
  223.     }
  224.     /**
  225.      * @return mixed
  226.      */
  227.     public function getGTMBodyTag($forceLoading true)
  228.     {
  229.         if (!$this->gtmEnabled) {
  230.             return '';
  231.         }
  232.         if (!isset($this->gtmTagId[$this->locale])) {
  233.             return '';
  234.         }
  235.         $tag str_replace("__*GTMTAG*__"$this->gtmTagId[$this->locale], $this->googleBodyTag);
  236.         $forcedDisplay '';
  237.         if ($forceLoading) {
  238.             $forcedDisplay self::FORCE_DISPLAY_TEXT;
  239.         }
  240.         $tag str_replace("__*FORCEDISPLAY*__"$forcedDisplay$tag);
  241.         return $tag;
  242.     }
  243.     /**
  244.      * @return mixed
  245.      */
  246.     public function getGTMLayerTag($tracking$cart$actualRoute)
  247.     {
  248.         if (!$this->gtmEnabled) {
  249.             return '';
  250.         }
  251.         if ($tracking instanceof Tracking) {
  252.             $this->tracking $tracking;
  253.         }
  254.         if ($cart instanceof Cart) {
  255.             $this->cart $cart;
  256.         }
  257.         $layer = [
  258.             'tracking' => $this->getTrackingVariables(),
  259.             'user' => $this->getUserVariables(),
  260.         ];
  261.         $checkoutStep $this->getCheckoutStep($actualRoute);
  262.         switch ($checkoutStep) {
  263.             case 2:
  264.                 $layer['event'] = 'shipping';
  265.                 break;
  266.             case 3:
  267.                 $layer['event'] = 'checkout';
  268.                 break;
  269.             case 4:
  270.                 break;
  271.             case 99:
  272.                 $layer['event'] = 'confirmDoubleOrder';
  273.                 break;
  274.         }
  275.         $layer['ecommerce'] = $this->getCartVariables($checkoutStep);
  276.         $encodedLayer json_encode($layer);
  277.         return "<script>dataLayer = [{$encodedLayer}];</script>";
  278.     }
  279.     /**
  280.      * @return string
  281.      */
  282.     public function getGTMEvents($actualRoute)
  283.     {
  284.         $eventString '';
  285.         $eventString .= $this->getErrorEvent('login'self::GTM_SESSION_LOGIN_EVENT_KEY);
  286. //        $eventString .= $this->getErrorEvent(
  287. //            'codepromo',
  288. //            self::GTM_SESSION_PROMOCODE_EVENT_KEY,
  289. //            'error_coupon',
  290. //            self::GTM_SESSION_PROMOCODE_NAME_KEY
  291. //        );
  292.         $eventString .= $this->getErrorEvent('bank'self::GTM_SESSION_PAYMENT_ERROR_EVENT_KEY);
  293.         $eventString .= $this->getErrorEvent('swap_3ds'self::GTM_SESSION_PAYMENT_3DS_SWAP_EVENT_KEY);
  294.         $eventString .= $this->getErrorEvent('bank_3ds'self::GTM_SESSION_PAYMENT_3DS_ERROR_EVENT_KEY);
  295.         $eventString .= $this->getPageEvent($actualRoute);
  296.         return $this->gtmEnabled $eventString '';
  297.     }
  298.     /**
  299.      * @return array
  300.      */
  301.     private function getTrackingVariables()
  302.     {
  303.         $tracking $this->tracking;
  304.         if (!$tracking instanceof Tracking) {
  305.             $tracking $this->trackingFactory->getCurrentTracking();
  306.         }
  307.         $trackingInfo = [
  308.             'device' => $tracking->getDevice(),
  309.             'aff' => $tracking->getAff()->getAffiliateId(),
  310.             'o1' => $tracking->getO1(),
  311.             'o2' => $tracking->getO2(),
  312.             'o3' => $tracking->getO3(),
  313.             'o4' => $tracking->getO4(),
  314.             'o5' => $tracking->getO5(),
  315.             'rmkg' => (int) $tracking->getRmkg()
  316.         ];
  317.         if ($this->session->get(CartManager::DISCOUNT_CODE_KEY)) {
  318.             $trackingInfo['dcode'] = $this->session->get(CartManager::DISCOUNT_CODE_KEY);
  319.         }
  320.         if ($this->session->has(UtmTrackingListener::UTM_CONTENT)) {
  321.             $trackingInfo[UtmTrackingListener::UTM_CONTENT] = $this->session->get(UtmTrackingListener::UTM_CONTENT);
  322.         }
  323.         return $trackingInfo;
  324.     }
  325.     /**
  326.      * @return array
  327.      */
  328.     private function getCartVariables($checkoutStep)
  329.     {
  330.         $cart $this->getCurrentCart();
  331.         if (!$cart instanceof Cart) {
  332.             return [];
  333.         }
  334.         $currencyKey self::GTM_UA_CURRENCY_KEY;
  335.         $productsKey self::GTM_UA_PRODUCTS_KEY;
  336.         $productIdKey self::GTM_UA_PRODUCT_ID_KEY;
  337.         $productNameKey self::GTM_UA_PRODUCT_NAME_KEY;
  338.         $purchaseRevenueKey self::GTM_UA_PURCHASE_REVENUE_KEY;
  339.         $purchaseRevenueNotVatKey self::GTM_UA_PURCHASE_REVENUE_NOT_VAT_KEY;
  340.         $purchaseId self::GTM_UA_PURCHASE_ID_KEY;
  341.         if (self::GTM_TYPE_GA4 === $this->googleTagManagerVersion) {
  342.             $currencyKey self::GTM_GA4_CURRENCY_KEY;
  343.             $productsKey self::GTM_GA4_PRODUCTS_KEY;
  344.             $productIdKey self::GTM_GA4_PRODUCT_ID_KEY;
  345.             $productNameKey self::GTM_GA4_PRODUCT_NAME_KEY;
  346.             $purchaseRevenueKey self::GTM_GA4_PURCHASE_REVENUE_KEY;
  347.             $purchaseRevenueNotVatKey self::GTM_GA4_PURCHASE_REVENUE_NOT_VAT_KEY;
  348.             $purchaseId self::GTM_GA4_PURCHASE_ID_KEY;
  349.         }
  350.         $cartArray = [
  351.             $currencyKey => 'EUR',
  352.             'checkout_step' => $checkoutStep,
  353.             'coupon' => $this->getCartPromoCode(),
  354.             'coaching' => (int) $this->getCartCoaching(),
  355.         ];
  356.         $commonActionFields = [
  357.             $currencyKey => 'EUR',
  358.             'coupon' => $this->getCartPromoCode(),
  359.             'coaching' => (int) $this->getCartCoaching()
  360.         ];
  361.         $productArray = [];
  362.         $cartPacks $cart->getPacks();
  363.         $packArray = [];
  364.         $packNormalPrice = [];
  365.         /** @var Pack $cartPack */
  366.         foreach ($cartPacks as $cartPack) {
  367.             $packNormalPrice[$cartPack->getPackId()] = $cartPack->getPackPriceReduced() / 100;
  368.             $packArray[$cartPack->getPackId()] = $cartPack;
  369.         }
  370.         if (!== $checkoutStep) {
  371.             // For Brulafine for "items" array data:
  372.             //   1. For Custom Packs -> we send Product information (product price, product Name, etc.)
  373.             //   2. For Auto Packs -> we send Pack information (pack price, pack Name, etc.)
  374.             // For Slimalis its by Pack information.
  375.             switch($this->siteName) {
  376.                 case 'brulafine':
  377.                     if (Pack::CUSTOM_PACK === $cartPack->getPackType()) {
  378.                         /** @var Pack $cartPack */
  379.                         foreach ($cartPacks as $cartPack) {
  380.                             /** @var PackProduct $packProduct */
  381.                             foreach ($cartPack->getPackProducts() as $packProduct) {
  382.                                 if (Product::ELECTRONIC_PRODUCT === $packProduct->getProduct()->getProductType()) {
  383.                                     continue;
  384.                                 }
  385.                                 $product = [
  386.                                     $productNameKey => $packProduct->getProduct()->getProductName(),
  387.                                     'price' => (float)number_format(($packProduct->getProduct()->getProductPrice() / 100), 2),
  388.                                     'quantity' => $packProduct->getProductQuantity(),
  389.                                     $productIdKey => $packProduct->getProduct()->getProductOptions()['EAN'] ?? '',
  390.                                     'item_brand' => $this->brandName,
  391.                                 ];
  392.                                 $productArray[] = $product;
  393.                             }
  394.                         }
  395.                     } else {
  396.                         /** @var Pack $cartPack */
  397.                         foreach ($cartPacks as $cartPack) {
  398.                             $product = [
  399.                                 $productNameKey => $this->packFactory->getMarketingPackName($cartPack),
  400.                                 'price' => (float) number_format(($cartPack->getPackPriceReduced() / 100), 2) ?? '-1',
  401.                                 'quantity' => 1// ATM we can only have 1 pack
  402.                                 $productIdKey => $cartPack->getPackOptions()['EAN'] ?? '',
  403.                                 'item_brand' => $this->brandName,
  404.                             ];
  405.                             $productArray[] = $product;
  406.                         }
  407.                     }
  408.                     $cartArray['cart_value'] = $this->getCartDiscountedRevenue();
  409.                     break;
  410.                 case 'slimalis':
  411.                     /** @var Pack $cartPack */
  412.                     foreach ($cartPacks as $cartPack) {
  413.                         $product = [
  414.                             $productNameKey => $this->packFactory->getMarketingPackName($cartPack),
  415.                             'price' => ($cartPack->getPackPriceReduced() / 100) ?? '-1',
  416.                             'quantity' => 1// ATM we can only have 1 pack
  417.                             $productIdKey => $cartPack->getPackOptions()['EAN'] ?? '',
  418.                             'item_brand' => $this->brandName,
  419.                         ];
  420.                         $productArray[] = $product;
  421.                     }
  422.                     break;
  423.             }
  424.         }
  425.         switch($checkoutStep) {
  426.             case 1:
  427.                 $cartArray['add']['actionField'] = $commonActionFields;
  428.                 $cartArray['add'][$productsKey] = $productArray;
  429.                 break;
  430.             case 2:
  431.                 $cartArray['shipping']['actionField'] = $commonActionFields;
  432.                 $cartArray['shipping'][$productsKey] = $productArray;
  433.                 break;
  434.             case 3:
  435.                 $cartArray['checkout']['actionField'] = $commonActionFields;
  436.                 $cartArray['checkout'][$productsKey] = $productArray;
  437.                 break;
  438.             case 4:
  439.                 $transaction $cart->getPaymentTransaction();
  440.                 $invoice = new TransactionInvoice($transaction$this->cartFactory$this->cartFactory->getInvoiceSiteId(), $this->logger);
  441.                 $invoiceArray $invoice->asArrayForWebservice();
  442.                 $cartArray['purchase']['actionField'][$purchaseId] = $this->cartFactory->getEncodedId($cart);
  443.                 $cartArray['purchase']['actionField'][$purchaseRevenueNotVatKey] = (float) round($invoiceArray['total_price_without_vat'], 2);
  444.                 $cartArray['purchase']['actionField'][$purchaseRevenueKey] = (float) round($invoiceArray['total_price'], 2);
  445.                 $cartArray['purchase']['actionField']['shipping_no_vat'] = (float) round($invoiceArray['total_shipping_without_vat'], 2);
  446.                 $cartArray['purchase']['actionField']['shipping'] = $invoiceArray['total_shipping'];
  447.                 $cartArray['purchase']['actionField']['method'] = $invoice->getPaymentMethodLabel();
  448.                 $cartArray['purchase']['actionField']['delivery'] = 'standard';
  449.                 $cartArray['purchase']['actionField']['coaching'] = $cart->hasCoaching();
  450.                 $cartArray['purchase']['actionField']['tax'] = (float) round($invoiceArray['total_vat_discounted'], 2);
  451.                 $cartArray['purchase']['actionField']['discount'] = (float) round($invoiceArray['total_discount'], 2);
  452.                 $cartArray['purchase']['actionField']['discounted_revenue_not_vat'] = (float) round(($invoiceArray['total_price_without_vat_with_discount']), 2);
  453.                 $cartArray['purchase']['actionField']['discounted_revenue'] = (float) round(($invoiceArray['total_price_with_discount']), 2);
  454.                 // For Brulafine for items array data:
  455.                 //   1. For Custom Packs -> we send Product information (product price, product Name, etc.)
  456.                 //   2. For Auto Packs -> we send Pack information (pack price, pack Name, etc.)
  457.                 // For Slimalis its stays by Pack info.
  458.                 switch($this->siteName) {
  459.                     case 'brulafine':
  460.                         if (Pack::CUSTOM_PACK === $cartPack->getPackType()) {
  461.                             /** @var TransactionInvoicePack $invoicePack */
  462.                             foreach ($invoice->getPacks() as $invoicePack) {
  463.                                 /** @var TransactionInvoiceItem $transactionInvoiceItem */
  464.                                 foreach ($invoicePack->getItems() as $transactionInvoiceItem) {
  465.                                     if ($transactionInvoiceItem->isElectronic()) {
  466.                                         continue;
  467.                                     }
  468.                                     $product = [
  469.                                         $productNameKey => $transactionInvoiceItem->getName(),
  470.                                         'price' => (float) number_format($transactionInvoiceItem->getUnitPrice() / 1001),
  471.                                         'price_not_vat' => (float) number_format($transactionInvoiceItem->getUnitPriceWithoutVat() / 1001),
  472.                                         'quantity' => $transactionInvoiceItem->getQuantity(), // ATM we can only have 1 pack
  473.                                         $productIdKey => $transactionInvoiceItem->getPackEAN(),
  474.                                         'revenue_no_vat' => (float) number_format(($transactionInvoiceItem->getUnitPriceWithoutVat() * $transactionInvoiceItem->getQuantity()) / 1001),
  475.                                         'revenue' => (float) number_format(($transactionInvoiceItem->getUnitPrice() * $transactionInvoiceItem->getQuantity()) / 1001),
  476.                                         'item_brand' => $this->brandName,
  477.                                         'vat_applied' => $invoicePack->getVatRate(),
  478.                                         'discount' => $invoicePack->getDiscount()
  479.                                     ];
  480.                                     $productArray[] = $product;
  481.                                 }
  482.                             }
  483.                         } else {
  484.                             /** @var TransactionInvoicePack $invoicePack */
  485.                             foreach ($invoice->getPacks() as $invoicePack) {
  486.                                 $product = [
  487.                                     $productNameKey => $this->packFactory->getMarketingPackName($packArray[$invoicePack->getId()]),
  488.                                     'price' => (float) number_format($packNormalPrice[$invoicePack->getId()], 2),
  489.                                     'price_not_vat' => (float) number_format($invoicePack->getPriceWithoutVat() / 1002),
  490.                                     'quantity' => 1// ATM we can only have 1 pack
  491.                                     $productIdKey => $invoicePack->getEan(),
  492.                                     'revenue_no_vat' => (float) number_format($invoicePack->getPriceWithoutVat() / 1002),
  493.                                     'revenue' => $invoicePack->getPrice() / 100,
  494.                                     'item_brand' => $this->brandName,
  495.                                     'vat_applied' => $invoicePack->getVatRate(),
  496.                                     'discount' => $invoicePack->getDiscount()
  497.                                 ];
  498.                                 $productArray[] = $product;
  499.                             }
  500.                         }
  501.                         break;
  502.                     case 'slimalis':
  503.                         /** @var TransactionInvoicePack $invoicePack */
  504.                         foreach ($invoice->getPacks() as $invoicePack) {
  505.                             $product = [
  506.                                 $productNameKey => $this->packFactory->getMarketingPackName($packArray[$invoicePack->getId()]),
  507.                                 'price' => (float) number_format($packNormalPrice[$invoicePack->getId()], 2),
  508.                                 'productPriceTtc' => $packNormalPrice[$invoicePack->getId()],
  509.                                 'price_not_vat' => (float) number_format($invoicePack->getPriceWithoutVat() / 1002),
  510.                                 'quantity' => 1// ATM we can only have 1 pack
  511.                                 $productIdKey => $invoicePack->getEan(),
  512.                                 'revenue_not_vat' => (float) round($invoicePack->getPriceWithoutVat() / 1001),
  513.                                 'revenue' => (float) round($invoicePack->getPrice() / 1002),
  514.                                 'item_brand' => $this->brandName,
  515.                                 'vat_applied' => $invoicePack->getVatRate(),
  516.                                 'discount' => $invoicePack->getDiscount()
  517.                             ];
  518.                             $productArray[] = $product;
  519.                         }
  520.                         break;
  521.                 }
  522.                 $cartArray['purchase'][$productsKey] = $productArray;
  523.                 break;
  524.             case 99:
  525.                 $cartArray['doubleOrder']['actionField'] = $commonActionFields;
  526.                 $cartArray['doubleOrder'][$productsKey] = $productArray;
  527.                 break;
  528.         }
  529.         return $cartArray;
  530.     }
  531.     /**
  532.      * @return array
  533.      */
  534.     private function getUserVariables()
  535.     {
  536.         $token $this->tokenStorage->getToken();
  537.         if (null !== $token) {
  538.             $user $token->getUser();
  539.         } else {
  540.             $user null;
  541.         }
  542.         $userData = [
  543.             'is_logged_in' => false,
  544.             'id' => null
  545.         ];
  546.         if ($user instanceof User) {
  547.             $userData['is_logged_in'] = true;
  548.             $userData['id'] = $user->getId();
  549.             $userData['has_fb_login'] = $user->getFacebookId() ? true false;
  550.             $last24 false;
  551.             $registrationDate $user->getCreationStamp()->getTimestamp();
  552.             $now = (new \DateTime())->getTimestamp();
  553.             if (($registrationDate 86400) > $now) {
  554.                 $last24 true;
  555.             }
  556.             $userData['registered_in_last_24_h'] = $last24;
  557.         }
  558.         return $userData;
  559.     }
  560.     /**
  561.      * @return string
  562.      */
  563.     private function getCartPromoCode()
  564.     {
  565.         $cart $this->getCurrentCart();
  566.         if (!$cart instanceof Cart) {
  567.             return '';
  568.         }
  569.         if ($cart->getDiscountCode() instanceof DiscountCode) {
  570.             return $cart->getDiscountCode()->getDiscountCodeName();
  571.         }
  572.         return '';
  573.     }
  574.     /**
  575.      * @return bool
  576.      */
  577.     private function getCartCoaching()
  578.     {
  579.         $cart $this->getCurrentCart();
  580.         $coaching false;
  581.         if ($cart instanceof Cart && $cart->hasCoaching()) {
  582.             $coaching true;
  583.         }
  584.         return $coaching;
  585.     }
  586.     /**
  587.      * @param $actualRoute
  588.      * @return int|mixed
  589.      */
  590.     private function getCheckoutStep($actualRoute)
  591.     {
  592.         if (isset($this->steps[$actualRoute]) && $this->steps[$actualRoute]) {
  593.             return $this->steps[$actualRoute];
  594.         }
  595.         // if we are not in one of those routes, then we are on step 0.
  596.         return 0;
  597.     }
  598.     /**
  599.      * @return object|void
  600.      */
  601.     private function getCurrentCart()
  602.     {
  603.         // if not initialised then initialise it
  604.         if (=== $this->cart) {
  605.             $this->cart $this->cartFactory->resolveCurrentCart();
  606.         }
  607.         return $this->cart;
  608.     }
  609.     private function getCartDiscountedRevenue()
  610.     {
  611.         $values $this->cartFactory->computeCartTotal($this->getCurrentCart());
  612.         return (float) number_format(($values['packPriceReduced'] / 100), 2);
  613.     }
  614.     /**
  615.      * @param string $type
  616.      * @param string $sessionKey
  617.      * @param null $additionnalVar
  618.      * @param null $additionnalData
  619.      * @return string
  620.      */
  621.     private function getErrorEvent($type 'login'$sessionKey self::GTM_SESSION_LOGIN_EVENT_KEY$additionnalVar null$additionnalData null)
  622.     {
  623.         $event '';
  624.         $error $this->session->get($sessionKey);
  625.         if ($error) {
  626.             $variableArray = ['errorString' => $error];
  627.             if ($additionnalVar) {
  628.                 $variableArray[$additionnalVar] = $this->session->get($additionnalData);
  629.             }
  630.             $event $this->getEventCode($type$variableArray);
  631.             $this->session->remove($sessionKey);
  632.         }
  633.         return $event;
  634.     }
  635.     /**
  636.      * @param $eventName
  637.      * @param array $variables
  638.      */
  639.     private function getEventCode($eventName$variables = [])
  640.     {
  641.         $event json_encode(array_merge(['event' => $eventName], $variables));
  642.         $eventString = <<<TAG
  643. <script>
  644. dataLayer.push({$event});
  645. </script>
  646. TAG;
  647.         return $eventString;
  648.     }
  649.     /**
  650.      * @param $actualRoute
  651.      * @return string
  652.      */
  653.     private function getPageEvent($actualRoute)
  654.     {
  655.         $checkoutStep $this->getCheckoutStep($actualRoute);
  656.         switch ($checkoutStep) {
  657.             case 4:
  658.                 $event json_encode(['event' => 'transaction']);
  659.                 $eventString = <<<TAG
  660. <script>
  661. dataLayer.push({$event});
  662. </script>
  663. TAG;
  664.                 return $eventString;
  665.                 break;
  666.         }
  667.     }
  668.     /**
  669.      * @return string
  670.      */
  671.     public function getName()
  672.     {
  673.         return 'google_tag_manager_extension';
  674.     }
  675. }