Skip to content

Commit bc3ac43

Browse files
authored
Merge pull request #130 from Hlavtox/minor-cleanup
GA4 fixes and improvements
2 parents cb7f02f + b55a8bd commit bc3ac43

18 files changed

Lines changed: 371 additions & 310 deletions

classes/Database/Install.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public function registerHooks()
100100
{
101101
return $this->module->registerHook('displayHeader') &&
102102
$this->module->registerHook('displayAdminOrder') &&
103+
$this->module->registerHook('displayBeforeBodyClosingTag') &&
103104
$this->module->registerHook('displayFooter') &&
104105
$this->module->registerHook('displayFooterProduct') &&
105106
$this->module->registerHook('displayOrderConfirmation') &&

classes/Form/ConfigurationForm.php

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,6 @@ public function generate()
8787
'title' => $this->module->trans('Settings', [], 'Modules.GAnalytics.Admin'),
8888
],
8989
'input' => [
90-
[
91-
'type' => 'text',
92-
'label' => $this->module->trans('Google Analytics Tracking ID', [], 'Modules.GAnalytics.Admin'),
93-
'name' => 'GA_ACCOUNT_ID',
94-
'size' => 20,
95-
'required' => true,
96-
'hint' => $this->module->trans('This information is available in your Google Analytics account', [], 'Modules.GAnalytics.Admin'),
97-
],
9890
[
9991
'type' => 'switch',
10092
'label' => $this->module->trans('Enable Google Analytics 4', [], 'Modules.GAnalytics.Admin'),
@@ -111,6 +103,15 @@ public function generate()
111103
'label' => $this->module->trans('No', [], 'Modules.GAnalytics.Admin'),
112104
],
113105
],
106+
'desc' => $this->module->trans('Universal analytics will stop processing data on July 1, 2023. We recommend switching to Google Analytics 4 as soon as possible.', [], 'Modules.GAnalytics.Admin'),
107+
],
108+
[
109+
'type' => 'text',
110+
'label' => $this->module->trans('Google Analytics Tracking ID', [], 'Modules.GAnalytics.Admin'),
111+
'name' => 'GA_ACCOUNT_ID',
112+
'size' => 20,
113+
'required' => true,
114+
'desc' => $this->module->trans('This information is available in your Google Analytics account. GA4 tracking ID starts with G-, Universal Analytics with UA-.', [], 'Modules.GAnalytics.Admin'),
114115
],
115116
[
116117
'type' => 'switch',

classes/GoogleAnalyticsTools.php

Lines changed: 107 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -64,25 +64,40 @@ public function addTransaction($products, $transaction)
6464
}
6565

6666
if ($this->isV4Enabled) {
67-
$js = 'gtag(\'event\', \'purchase\', {
68-
"transaction_id": "' . $transaction['id'] . '",
69-
"items": [';
67+
$callbackData = [
68+
'orderid' => $transaction['id'],
69+
'customer' => $transaction['customer'],
70+
];
71+
72+
$eventData = [
73+
'transaction_id' => (int) $transaction['id'],
74+
'affiliation' => $transaction['affiliation'],
75+
'value' => (float) $transaction['revenue'],
76+
'tax' => (float) $transaction['tax'],
77+
'shipping' => (float) $transaction['shipping'],
78+
'currency' => $transaction['currency'],
79+
'items' => [],
80+
'event_callback' => "function() {
81+
$.get('" . $transaction['url'] . "', " . json_encode($callbackData, JSON_UNESCAPED_UNICODE) . ');
82+
}',
83+
];
7084

71-
$isFirst = true;
7285
foreach ($products as $product) {
73-
if (!$isFirst) {
74-
$js .= ',';
75-
}
76-
$js .= '{
77-
"item_id": "' . $product['id'] . '",
78-
"item_name": "' . $product['name'] . '",
79-
"quantity": "' . $product['quantity'] . '",
80-
"price": "' . $product['price'] . '"
81-
}';
82-
$isFirst = false;
86+
$eventData['items'][] = [
87+
'item_id' => (int) $product['id'],
88+
'item_name' => $product['name'],
89+
'quantity' => (int) $product['quantity'],
90+
'price' => (float) $product['price'],
91+
];
8392
}
84-
$js .= ']});';
93+
94+
$js = $this->renderEvent(
95+
'purchase',
96+
$eventData,
97+
['event_callback']
98+
);
8599
} else {
100+
unset($transaction['currency']);
86101
$js = '';
87102
foreach ($products as $product) {
88103
$js .= 'MBG.add(' . json_encode($product) . ');';
@@ -133,26 +148,26 @@ public function addProductClick($products, $currencyIsoCode)
133148
$js = '';
134149
if ($this->isV4Enabled) {
135150
foreach ($products as $key => $product) {
151+
$eventData = [
152+
'items' => [
153+
'item_id' => (int) $product['id'],
154+
'item_name' => $product['name'],
155+
'quantity' => (int) $product['quantity'],
156+
'price' => (float) $product['price'],
157+
'currency' => $currencyIsoCode,
158+
'index' => (int) $product['position'],
159+
'item_brand' => $product['brand'],
160+
'item_category' => $product['category'],
161+
'item_list_id' => $product['list'],
162+
'item_variant' => $product['variant'],
163+
],
164+
];
165+
136166
$productId = explode('-', $product['id']);
137167
$js .= '$(\'article[data-id-product="' . $productId[0] . '"] a.quick-view\').on(
138168
"click",
139169
function() {
140-
gtag("event", "select_item", {
141-
items: [
142-
{
143-
item_id: "' . $product['id'] . '",
144-
item_name: "' . $product['name'] . '",
145-
quantity: "' . $product['quantity'] . '",
146-
price: "' . $product['price'] . '",
147-
currency: "' . $currencyIsoCode . '",
148-
index: ' . $product['position'] . ',
149-
item_brand: "' . $product['brand'] . '",
150-
item_category: "' . $product['category'] . '",
151-
item_list_id: "' . $product['list'] . '",
152-
item_variant: "' . $product['variant'] . '",
153-
}
154-
]
155-
})
170+
gtag("event", "select_item", ' . json_encode($eventData, JSON_UNESCAPED_UNICODE) . ')
156171
});';
157172
}
158173
} else {
@@ -180,22 +195,25 @@ public function addProductClickByHttpReferal($products, $currencyIsoCode)
180195
$js = '';
181196
if ($this->isV4Enabled) {
182197
foreach ($products as $key => $product) {
183-
$js .= 'gtag("event", "select_item", {
184-
items: [
185-
{
186-
item_id: "' . $product['id'] . '",
187-
item_name: "' . $product['name'] . '",
188-
quantity: "' . $product['quantity'] . '",
189-
price: "' . $product['price'] . '",
190-
currency: "' . $currencyIsoCode . '",
191-
index: ' . $product['position'] . ',
192-
item_brand: "' . $product['brand'] . '",
193-
item_category: "' . $product['category'] . '",
194-
item_list_id: "' . $product['list'] . '",
195-
item_variant: "' . $product['variant'] . '",
196-
}
197-
]
198-
});';
198+
$eventData = [
199+
'items' => [
200+
'item_id' => (int) $product['id'],
201+
'item_name' => $product['name'],
202+
'quantity' => (int) $product['quantity'],
203+
'price' => (float) $product['price'],
204+
'currency' => $currencyIsoCode,
205+
'index' => (int) $product['position'],
206+
'item_brand' => $product['brand'],
207+
'item_category' => $product['category'],
208+
'item_list_id' => $product['list'],
209+
'item_variant' => $product['variant'],
210+
],
211+
];
212+
213+
$js .= $this->renderEvent(
214+
'select_item',
215+
$eventData
216+
);
199217
}
200218
} else {
201219
foreach ($products as $product) {
@@ -228,4 +246,46 @@ public function addProductFromCheckout($products)
228246

229247
return $js;
230248
}
249+
250+
/**
251+
* Encodes array of data into JSON, optionally ignoring some of the values
252+
*
253+
* @param array $data Data pairs
254+
* @param array $ignoredKeys Values of these keys won't be encoded, for literal output of functions
255+
*
256+
* @return string json encoded data
257+
*/
258+
public function jsonEncodeWithBlacklist($data, $ignoredKeys = [])
259+
{
260+
$return = [];
261+
262+
foreach ($data as $k => $v) {
263+
if (in_array($k, $ignoredKeys)) {
264+
$return[] = json_encode($k, JSON_UNESCAPED_UNICODE) . ': ' . $v;
265+
} else {
266+
$return[] = json_encode($k, JSON_UNESCAPED_UNICODE) . ': ' . json_encode($v, JSON_UNESCAPED_UNICODE);
267+
}
268+
}
269+
270+
return '{' . implode(', ', $return) . '}';
271+
}
272+
273+
/**
274+
* Renders gtag event and encodes the data. You can optionally pass which data keys you want to
275+
* output in a raw way - callbacks for example.
276+
*
277+
* @param string $eventName
278+
* @param array $eventData
279+
* @param array $ignoredKeys Values of these keys won't be encoded, for literal output of functions
280+
*
281+
* @return string render gtag event for output
282+
*/
283+
public function renderEvent($eventName, $eventData, $ignoredKeys = [])
284+
{
285+
return sprintf(
286+
'gtag("event", "%1$s", %2$s);',
287+
$eventName,
288+
$this->jsonEncodeWithBlacklist($eventData, $ignoredKeys)
289+
);
290+
}
231291
}

classes/Hook/HookActionCarrierProcess.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,15 @@ protected function getUniversalAnalytics(string $carrierName)
7878

7979
protected function getGoogleAnalytics4(string $carrierName)
8080
{
81-
return 'gtag("event", "add_shipping_info", {
82-
currency: "' . $this->context->currency->iso_code . '",
83-
value: ' . $this->context->cart->getCartTotalPrice() . ',
84-
shipping_tier: "' . $carrierName . '"
85-
});';
81+
$eventData = [
82+
'currency' => $this->context->currency->iso_code,
83+
'value' => (float) $this->context->cart->getSummaryDetails()['total_price'],
84+
'shipping_tier' => $carrierName,
85+
];
86+
87+
return $this->module->getTools()->renderEvent(
88+
'add_shipping_info',
89+
$eventData
90+
);
8691
}
8792
}

classes/Hook/HookActionOrderStatusPostUpdate.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,13 @@ protected function getUniversalAnalytics($idOrder)
106106

107107
protected function getGoogleAnalytics4($idOrder)
108108
{
109-
return 'gtag("event", "refund", {
110-
currency: "' . $this->context->currency->iso_code . '",
111-
transaction_id: ' . $idOrder . '
112-
});';
109+
$eventData = [
110+
'transaction_id' => (int) $idOrder,
111+
];
112+
113+
return $this->module->getTools()->renderEvent(
114+
'refund',
115+
$eventData
116+
);
113117
}
114118
}

classes/Hook/HookActionProductCancel.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,20 @@ protected function getUniversalAnalytics(int $idOrder, string $idProduct, float
101101

102102
protected function getGoogleAnalytics4(int $idOrder, string $idProduct, float $quantity, string $nameProduct)
103103
{
104-
return 'gtag("event", "refund", {
105-
currency: "' . $this->context->currency->iso_code . '",
106-
transaction_id: ' . $idOrder . ',
107-
items: [
108-
{
109-
item_id: ' . $idProduct . ',
110-
item_name: "' . $nameProduct . '",
111-
quantity: ' . $quantity . '
112-
}
113-
]
114-
});';
104+
$eventData = [
105+
'transaction_id' => (int) $idOrder,
106+
'items' => [
107+
[
108+
'item_id' => (int) $idProduct,
109+
'item_name' => $nameProduct,
110+
'quantity' => (int) $quantity,
111+
],
112+
],
113+
];
114+
115+
return $this->module->getTools()->renderEvent(
116+
'refund',
117+
$eventData
118+
);
115119
}
116120
}

classes/Hook/HookDisplayBackOfficeHeader.php

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,30 @@ public function run()
9696
],
9797
'id_order = ' . (int) $row['id_order'] . ' AND id_shop = ' . (int) $this->context->shop->id
9898
);
99+
100+
// Generate transaction event
99101
if ($isV4Enabled) {
100-
$gaScripts .= 'gtag("event", "purchase", {
101-
transaction_id: "' . $transaction['id'] . '",
102-
affiliation: "' . $transaction['affiliation'] . '",
103-
value: ' . $transaction['revenue'] . ',
104-
tax: ' . $transaction['tax'] . ',
105-
shipping: ' . $transaction['shipping'] . ',
106-
currency: "' . $this->context->currency->iso_code . '"
107-
});';
102+
$callbackData = [
103+
'orderid' => (int) $transaction['id'],
104+
'customer' => (int) $transaction['customer'],
105+
];
106+
107+
$eventData = [
108+
'transaction_id' => (int) $transaction['id'],
109+
'affiliation' => $transaction['affiliation'],
110+
'value' => (float) $transaction['revenue'],
111+
'tax' => (float) $transaction['tax'],
112+
'shipping' => (float) $transaction['shipping'],
113+
'currency' => $this->context->currency->iso_code,
114+
'event_callback' => "function() {
115+
$.get('" . $transaction['url'] . "', " . json_encode($callbackData, JSON_UNESCAPED_UNICODE) . ');
116+
}',
117+
];
118+
$gaScripts .= $this->module->getTools()->renderEvent(
119+
'purchase',
120+
$eventData,
121+
['event_callback']
122+
);
108123
} else {
109124
$gaScripts .= 'MBG.addTransaction(' . json_encode($transaction) . ');';
110125
}

0 commit comments

Comments
 (0)