<?php
namespace App\Twig;
use App\DTO\AppDTO;
use App\Entity\Prod;
use App\Env;
use App\Repository\CatRepository;
use App\Repository\OrderRepository;
use App\Repository\UserRepository;
use Symfony\Component\HttpFoundation\RequestStack;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class GoogleAnalyticsEvents extends AbstractExtension
{
public function __construct(
private RequestStack $requestStack,
private AppDTO $app,
private OrderRepository $orderRepository,
private CatRepository $catRepository,
)
{
}
public function getFunctions(): array
{
return [
new TwigFunction('ga_events_init', [$this, 'init']),
new TwigFunction('ga_events_search', [$this, 'searchResults']),
new TwigFunction('ga_events_prodlist', [$this, 'prodList']),
new TwigFunction('ga_events_prodcont', [$this, 'prodCont']),
new TwigFunction('ga_events_addtocart', [$this, 'addToCart']),
new TwigFunction('ga_events_deletefromcart', [$this, 'deleteFromCart']),
new TwigFunction('ga_events_cart', [$this, 'cartItemList']),
new TwigFunction('ga_events_checkout_begin', [$this, 'checkoutBegin']),
new TwigFunction('ga_events_checkout_finish', [$this, 'checkoutFinish']),
new TwigFunction('ga_events_checkout_client_email', [$this, 'clientEmail']),
];
}
public function getName(): string
{
return 'app_google_analytics_extension';
}
public function init(): string
{
if (empty(Env::code_gtm())) {
return '';
}
$url = $this->requestStack->getCurrentRequest()->getPathInfo();
if (strstr($url, 'checkout/completed') || strstr($url, 'checkout/finish')) {
return '<script>
window.dataLayer = window.dataLayer || [];
function gtag(arguments) {
window.dataLayer.push(arguments);
}
</script>';
} else {
return '<script>
window.dataLayer = window.dataLayer || [];
function gtag(arguments) {
window.dataLayer.push(arguments);
}
</script>';
}
}
/**
*
* @param string $q
* @param \App\Entity\Prod[] $prods
* @return string
*/
public function searchResults(?string $q, array $prods)
{
if (empty(Env::code_gtm())) {
return '';
}
$sum = 0;
$i = 0;
$i = 0;
foreach ($prods as $prod) {
$i++;
if ($i > 10) {
break;
}
$sum += $prod->getPrice() * (100 - $prod->getSkidka()) / 100;
}
$result = '<script>
gtag("event", "view_search_results", {
search_term: "'.$q.'",
currency: "'.Env::currency_code().'",
value: '.round($sum, Env::price_precission()).',
items: [';
$i = 0;
foreach ($prods as $prod) {
$i++;
if ($i > 10) {
break;
}
$result .= '
{
id: "'.$prod->getId().'-'.$this->requestStack->getCurrentRequest()->getLocale().'",
name: "'.str_replace('"', '', $prod->getName()).'",
price: '.round(($prod->getPrice() * (100 - $prod->getSkidka()) / 100), Env::price_precission()).',
google_business_vertical: "retail"
}';
if ($i < 10) {
$result .= ',';
}
}
$result .= '
]
});</script>';
return $result;
}
/**
*
* @param \App\Entity\Prod[] $prods
* @return string
*/
public function prodList(array $prods)
{
if (empty(Env::code_gtm())) {
return '';
}
$currency = Env::currency_code();
$locale = $this->requestStack->getCurrentRequest()->getLocale();
$result = '<script>
window.dataLayer.push({
event: "view_item_list",
ecommerce: {
items: [';
$i = 0;
$total = min(count($prods), 10);
foreach ($prods as $prod) {
$cat = $this->catRepository->get($prod->getCat());
$i++;
if ($i > 10) {
break;
}
$price = round(($prod->getPrice() * (100 - $prod->getSkidka()) / 100), Env::price_precission());
$result .= '
{
item_name: "'.str_replace('"', '', $prod->getName()).'",
item_id: "'.$prod->getId().'",
price: '.$price.',
currency: "'.$currency.'",
item_category: "'.$cat->getName().'",
item_list_name: "Category List",
item_list_id: "category_list",
index: '.$i.',
quantity: 1
}';
if ($i < $total) {
$result .= ',';
}
}
$result .= '
]
}
});
</script>';
return $result;
}
// public function selectItemJs(Prod $prod, int $index = 1)
// {
// if (empty(Env::code_gtm())) {
// return '';
// }
// $currency = Env::currency_code();
// $price = round(
// $prod->getPrice() * (100 - $prod->getSkidka()) / 100,
// Env::price_precission()
// );
// return '
// function gaSelectItem_'.$prod->getId().'() {
// window.dataLayer.push({
// event: "select_item",
// ecommerce: {
// items: [{
// item_name: "'.str_replace('"', '', $prod->getName()).'",
// item_id: "'.$prod->getId().'",
// price: '.$price.',
// discount: '.intval($prod->getSkidka()).',
// currency: "'.$currency.'",
// item_category: "'.$prod->getCategoryName().'",
// item_category2: "'.$prod->getCategoryLevel2Name().'",
// item_list_name: "Category List",
// item_list_id: "ID2",
// index: '.$index.'
// }]
// }
// });
// }
// ';
// }
/**
*
* @param \App\Entity\Prod $prod
* @return string
*/
public function prodCont(Prod $prod, int $index = 1)
{
if (empty(Env::code_gtm())) {
return '';
}
$currency = Env::currency_code();
$price = round(
$prod->getPrice() * (100 - $prod->getSkidka()) / 100,
Env::price_precission()
);
$cat = $this->catRepository->get($prod->getCat());
$result = '<script>
window.dataLayer.push({
event: "view_item",
ecommerce: {
items: [{
item_name: "'.str_replace('"', '', $prod->getName()).'",
item_id: "'.$prod->getId().'",
price: '.$price.',
discount: '.intval($prod->getSkidka()).',
currency: "'.$currency.'",
item_category: "'.$cat->getName().'",
item_list_name: "Category List",
item_list_id: "ID2",
index: '.$index.'
}]
}
});
</script>';
return $result;
}
/**
*
* @param \App\Entity\Prod $prod
* @return string
*/
public function addToCart()
{
if (empty(Env::code_gtm())) {
return '';
}
return '
<script>
document.addEventListener("DOMContentLoaded", function() {
document.querySelectorAll(".add-to-cart").forEach(function(button) {
button.addEventListener("click", function() {
const item = {
item_name: this.dataset.name,
item_id: this.dataset.id,
price: parseFloat(this.dataset.price),
discount: parseInt(this.dataset.discount || 0),
currency: this.dataset.currency || "'.Env::currency_code().'",
item_brand: this.dataset.brand || "",
item_category: this.dataset.category || "",
item_category2: this.dataset.category2 || "",
item_list_name: this.dataset.listName || "Category List",
item_list_id: this.dataset.listId || "ID2",
index: parseInt(this.dataset.index || 1),
quantity: parseInt(this.dataset.quantity || 1)
};
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: "add_to_cart",
ecommerce: {
items: [item]
}
});
console.log("GA4 add_to_cart:", item);
});
});
});
</script>
';
}
public function deleteFromCart()
{
if (empty(Env::code_gtm())) {
return '';
}
return '
<script>
document.addEventListener("DOMContentLoaded", function() {
document.querySelectorAll(".delete-from-cart").forEach(function(button) {
button.addEventListener("click", function() {
const item = {
item_name: this.dataset.name,
item_id: this.dataset.id,
price: parseFloat(this.dataset.price),
discount: parseInt(this.dataset.discount || 0),
currency: this.dataset.currency || "'.Env::currency_code().'",
item_brand: this.dataset.brand || "",
item_category: this.dataset.category || "",
item_category2: this.dataset.category2 || "",
item_list_name: this.dataset.listName || "Category List",
item_list_id: this.dataset.listId || "ID2",
index: parseInt(this.dataset.index || 1),
quantity: parseInt(this.dataset.quantity || 1)
};
const cartValue = parseFloat(this.dataset.cartValue || item.price);
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: "view_cart",
ecommerce: {
currency: item.currency,
value: cartValue,
items: [item]
}
});
console.log("GA4 view_cart after delete:", item);
});
});
});
</script>
';
}
public function cartItemList(array $cart_items)
{
if (empty(Env::code_gtm())) {
return '';
}
$currency = Env::currency_code();
$locale = $this->requestStack->getCurrentRequest()->getLocale();
$result = '<script>
window.dataLayer.push({
event: "view_cart",
ecommerce: {
items: [';
$i = 0;
$total = min(count($cart_items), 10);
foreach ($cart_items as $cart_item) {
/** @var \App\Entity\Prod $prod */
$prod = $cart_item['prod'];
$cat = $this->catRepository->get($prod->getCat());
$i++;
if ($i > 10) {
break;
}
$price = round(($prod->getPrice() * (100 - $prod->getSkidka()) / 100), Env::price_precission());
$result .= '
{
item_name: "'.str_replace('"', '', $prod->getName()).'",
item_id: "'.$prod->getId().'",
price: '.$price.',
currency: "'.$currency.'",
item_category: "'.$cat->getName().'",
item_list_name: "Category List",
item_list_id: "category_list",
index: '.$i.',
quantity: 1
}';
if ($i < $total) {
$result .= ',';
}
}
$result .= '
]
}
});
</script>';
return $result;
}
/**
*
* @param array $prods
* @return string
*/
public function checkoutBegin(array $cart_items)
{
if (empty(Env::code_gtm())) {
return '';
}
$currency = Env::currency_code();
$sum = 0;
foreach ($cart_items as $v) {
$sum += $v['price'] * $v['num'];
}
$result = '<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: "begin_checkout",
ecommerce: {
currency: "'.$currency.'",
value: '.round($sum, Env::price_precission()).',
items: [';
$i = 0;
$total = count($cart_items);
foreach ($cart_items as $v) {
/** @var \App\Entity\Prod $prod */
$prod = $v["prod"];
$cat = $this->catRepository->get($prod->getCat());
$i++;
$price = round(
$v["price"],
Env::price_precission()
);
$result .= '
{
item_name: "'.str_replace('"', '', $prod->getName()).'",
item_id: "'.$prod->getId().'",
price: '.$price.',
discount: '.intval($prod->getSkidka()).',
currency: "'.$currency.'",
item_category: "'.$cat->getName().'",
item_list_name: "Category List",
item_list_id: "ID2",
index: '.$i.',
quantity: '.$v["num"].'
}';
if ($i < $total) {
$result .= ',';
}
}
$result .= '
]
}
});
</script>';
return $result;
}
public function checkoutFinish(int $order_id, float $amount, array $cart_items)
{
if (empty(Env::code_gtm())) {
return '';
}
$currency = Env::currency_code();
$order = $this->orderRepository->find($order_id);
$result = '<script>
window.dataLayer.push({
event: "purchase",
ecommerce: {
transaction_id: "'.$order_id.'",
value: '.round($amount, Env::price_precission()).',
currency: "'.$currency.'",
form_id: "'.$order->getUser().'",
form_name: "'.$order->getName().'",
number: "'.$order->getPhone().'",
email: "'.$order->getEmail().'",
items: [';
$total = count($cart_items);
$i = 0;
foreach ($cart_items as $v) {
/** @var \App\Entity\Prod $prod */
$prod = $v['prod'];
$i++;
$result .= '
{
item_name: "'.$prod->getName().'",
item_id: "'.$prod->getId().'",
price: '.round($v['price'], Env::price_precission()).',
currency: "'.$currency.'",
item_list_name: "Checkout",
item_list_id: "checkout",
quantity: '.$v['num'].'
}';
if ($i < $total) {
$result .= ',';
}
}
$result .= '
]
}
});
</script>';
return $result;
}
public function clientEmail(?string $email) {
return '';
}
}