1 | <?php |
||||||
2 | /** |
||||||
3 | * Instant Analytics plugin for Craft CMS |
||||||
4 | * |
||||||
5 | * Instant Analytics brings full Google Analytics support to your Twig templates |
||||||
6 | * |
||||||
7 | * @link https://nystudio107.com |
||||||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||||||
8 | * @copyright Copyright (c) 2017 nystudio107 |
||||||
0 ignored issues
–
show
|
|||||||
9 | */ |
||||||
0 ignored issues
–
show
|
|||||||
10 | |||||||
11 | namespace nystudio107\instantanalyticsGa4\services; |
||||||
12 | |||||||
13 | use Br33f\Ga4\MeasurementProtocol\Dto\Event\ItemBaseEvent; |
||||||
14 | use Br33f\Ga4\MeasurementProtocol\Dto\Event\PurchaseEvent; |
||||||
15 | use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemParameter; |
||||||
16 | use craft\base\Component; |
||||||
17 | use craft\commerce\elements\Order; |
||||||
18 | use craft\commerce\elements\Product; |
||||||
19 | use craft\commerce\elements\Variant; |
||||||
20 | use craft\commerce\models\LineItem; |
||||||
21 | use craft\commerce\Plugin as CommercePlugin; |
||||||
22 | use craft\elements\db\CategoryQuery; |
||||||
23 | use craft\elements\db\EntryQuery; |
||||||
24 | use craft\elements\db\TagQuery; |
||||||
25 | use nystudio107\instantanalyticsGa4\InstantAnalytics; |
||||||
26 | use yii\base\InvalidConfigException; |
||||||
27 | use function get_class; |
||||||
28 | |||||||
29 | /** |
||||||
30 | * Commerce Service |
||||||
31 | * |
||||||
32 | * @author nystudio107 |
||||||
0 ignored issues
–
show
Content of the @author tag must be in the form "Display Name <[email protected]>"
![]() |
|||||||
33 | * @package InstantAnalytics |
||||||
0 ignored issues
–
show
|
|||||||
34 | * @since 1.0.0 |
||||||
0 ignored issues
–
show
|
|||||||
35 | */ |
||||||
0 ignored issues
–
show
|
|||||||
36 | class Commerce extends Component |
||||||
37 | { |
||||||
38 | // Public Methods |
||||||
39 | // ========================================================================= |
||||||
40 | |||||||
41 | /** |
||||||
42 | * Enqueue analytics information for the completed order |
||||||
43 | * |
||||||
44 | * @param ?Order $order the Product or Variant |
||||||
45 | */ |
||||||
0 ignored issues
–
show
|
|||||||
46 | public function triggerOrderCompleteEvent(Order $order = null) |
||||||
47 | { |
||||||
48 | if ($order) { |
||||||
49 | $event = InstantAnalytics::$plugin->ga4->getAnalytics()->create()->PurchaseEvent(); |
||||||
50 | $this->addCommerceOrderToEvent($event, $order); |
||||||
51 | |||||||
52 | InstantAnalytics::$plugin->ga4->getAnalytics()->addEvent($event); |
||||||
53 | |||||||
54 | InstantAnalytics::$plugin->logAnalyticsEvent( |
||||||
0 ignored issues
–
show
The method
logAnalyticsEvent() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||||||
55 | 'Adding `Commerce - Order Complete event`: `{reference}` => `{price}`', |
||||||
56 | ['reference' => $order->reference, 'price' => $order->totalPrice], |
||||||
57 | __METHOD__ |
||||||
58 | ); |
||||||
59 | } |
||||||
60 | } |
||||||
61 | |||||||
62 | /** |
||||||
63 | * Enqueue analytics information for a new checkout flow |
||||||
64 | * |
||||||
65 | * @param ?Order $order |
||||||
0 ignored issues
–
show
|
|||||||
66 | */ |
||||||
0 ignored issues
–
show
|
|||||||
67 | public function triggerBeginCheckoutEvent(Order $order = null) |
||||||
68 | { |
||||||
69 | if ($order) { |
||||||
70 | $event = InstantAnalytics::$plugin->ga4->getAnalytics()->create()->BeginCheckoutEvent(); |
||||||
71 | // First, include the transaction data |
||||||
72 | $event->setCurrency($order->getPaymentCurrency()) |
||||||
73 | ->setValue($order->getTotalPrice()); |
||||||
74 | |||||||
75 | // Add each line item in the cart |
||||||
76 | $index = 1; |
||||||
77 | foreach ($order->lineItems as $lineItem) { |
||||||
78 | $this->addProductDataFromLineItem($event, $lineItem, $index); |
||||||
79 | $index++; |
||||||
80 | } |
||||||
81 | |||||||
82 | InstantAnalytics::$plugin->ga4->getAnalytics()->addEvent($event); |
||||||
83 | |||||||
84 | InstantAnalytics::$plugin->logAnalyticsEvent( |
||||||
85 | 'Adding `Commerce - Begin Checkout event``', |
||||||
86 | [], |
||||||
87 | __METHOD__ |
||||||
88 | ); |
||||||
89 | } |
||||||
90 | } |
||||||
91 | |||||||
92 | /** |
||||||
93 | * Send analytics information for the item added to the cart |
||||||
94 | * |
||||||
95 | * @param LineItem $lineItem the line item that was added |
||||||
96 | */ |
||||||
0 ignored issues
–
show
|
|||||||
97 | public function triggerAddToCartEvent(LineItem $lineItem): void |
||||||
98 | { |
||||||
99 | $event = InstantAnalytics::$plugin->ga4->getAnalytics()->create()->AddToCartEvent(); |
||||||
100 | $this->addProductDataFromLineItem($event, $lineItem); |
||||||
101 | InstantAnalytics::$plugin->ga4->getAnalytics()->addEvent($event); |
||||||
102 | |||||||
103 | InstantAnalytics::$plugin->logAnalyticsEvent( |
||||||
104 | 'Adding `Commerce - Add to Cart event`: `{title}` => `{quantity}`', |
||||||
105 | ['title' => $lineItem->purchasable->title ?? $lineItem->getDescription(), 'quantity' => $lineItem->qty], |
||||||
106 | __METHOD__ |
||||||
107 | ); |
||||||
108 | } |
||||||
109 | |||||||
110 | /** |
||||||
111 | * Send analytics information for the item removed from the cart |
||||||
112 | * |
||||||
113 | * @param LineItem $lineItem |
||||||
0 ignored issues
–
show
|
|||||||
114 | */ |
||||||
0 ignored issues
–
show
|
|||||||
115 | public function triggerRemoveFromCartEvent(LineItem $lineItem) |
||||||
116 | { |
||||||
117 | $event = InstantAnalytics::$plugin->ga4->getAnalytics()->create()->RemoveFromCartEvent(); |
||||||
118 | $this->addProductDataFromLineItem($event, $lineItem); |
||||||
119 | InstantAnalytics::$plugin->ga4->getAnalytics()->addEvent($event); |
||||||
120 | |||||||
121 | InstantAnalytics::$plugin->logAnalyticsEvent( |
||||||
122 | 'Adding `Commerce - Remove from Cart event`: `{title}` => `{quantity}`', |
||||||
123 | ['title' => $lineItem->purchasable->title ?? $lineItem->getDescription(), 'quantity' => $lineItem->qty], |
||||||
124 | __METHOD__ |
||||||
125 | ); |
||||||
126 | } |
||||||
127 | |||||||
128 | /** |
||||||
129 | * Add a product impression from a Craft Commerce Product or Variant |
||||||
130 | * |
||||||
131 | * @param Product|Variant|null $productVariant the Product or Variant |
||||||
0 ignored issues
–
show
|
|||||||
132 | * @throws InvalidConfigException |
||||||
0 ignored issues
–
show
|
|||||||
133 | */ |
||||||
0 ignored issues
–
show
|
|||||||
134 | public function addCommerceProductImpression(Variant|Product|null $productVariant): void |
||||||
135 | { |
||||||
136 | if ($productVariant) { |
||||||
137 | $event = InstantAnalytics::$plugin->ga4->getAnalytics()->create()->ViewItemEvent(); |
||||||
138 | $this->addProductDataFromProductOrVariant($event, $productVariant); |
||||||
139 | |||||||
140 | InstantAnalytics::$plugin->ga4->getAnalytics()->addEvent($event); |
||||||
141 | |||||||
142 | $sku = $productVariant instanceof Product ? $productVariant->getDefaultVariant()->sku : $productVariant->sku; |
||||||
143 | $name = $productVariant instanceof Product ? $productVariant->getName() : $productVariant->getProduct()->getName(); |
||||||
0 ignored issues
–
show
The method
getProduct() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() The function
craft\commerce\elements\Variant::getProduct() has been deprecated: in 5.0.0. Use [[getOwner()]] instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
144 | InstantAnalytics::$plugin->logAnalyticsEvent( |
||||||
145 | 'Adding view item event for `{sku}` - `{name}` - `{name}` - `{index}`', |
||||||
146 | ['sku' => $sku, 'name' => $name], |
||||||
147 | __METHOD__ |
||||||
148 | ); |
||||||
149 | } |
||||||
150 | } |
||||||
151 | |||||||
152 | /** |
||||||
153 | * Add a product list impression from a Craft Commerce Product or Variant list |
||||||
154 | * |
||||||
155 | * @param Product[]|Variant[] $products |
||||||
0 ignored issues
–
show
|
|||||||
156 | * @param string $listName |
||||||
0 ignored issues
–
show
|
|||||||
157 | */ |
||||||
0 ignored issues
–
show
|
|||||||
158 | public function addCommerceProductListImpression(array $products, string $listName = 'default'): void |
||||||
159 | { |
||||||
160 | if (!empty($products)) { |
||||||
161 | $event = InstantAnalytics::$plugin->ga4->getAnalytics()->create()->ViewItemListEvent(); |
||||||
162 | foreach ($products as $index => $productVariant) { |
||||||
163 | $this->addProductDataFromProductOrVariant($event, $productVariant, $index, $listName); |
||||||
164 | } |
||||||
165 | |||||||
166 | InstantAnalytics::$plugin->ga4->getAnalytics()->addEvent($event); |
||||||
167 | |||||||
168 | InstantAnalytics::$plugin->logAnalyticsEvent( |
||||||
169 | 'Adding view item list event. Listing {number} of items from the `{listName}` list.', |
||||||
170 | ['number' => count($products), 'listName' => $listName], |
||||||
171 | __METHOD__ |
||||||
172 | ); |
||||||
173 | } |
||||||
174 | } |
||||||
175 | |||||||
176 | /** |
||||||
177 | * Add a Craft Commerce OrderModel to a Purchase Event |
||||||
178 | * |
||||||
179 | * @param PurchaseEvent $event The PurchaseEvent |
||||||
180 | * @param Order $order |
||||||
0 ignored issues
–
show
|
|||||||
181 | */ |
||||||
0 ignored issues
–
show
|
|||||||
182 | protected function addCommerceOrderToEvent(PurchaseEvent $event, Order $order) |
||||||
183 | { |
||||||
184 | // First, include the transaction data |
||||||
185 | $event->setCurrency($order->getPaymentCurrency()) |
||||||
186 | ->setTransactionId($order->reference) |
||||||
187 | ->setValue($order->getTotalPrice()) |
||||||
188 | ->setTax($order->getTotalTax()) |
||||||
189 | ->setShipping($order->getTotalShippingCost()); |
||||||
190 | |||||||
191 | // Coupon code |
||||||
192 | if ($order->couponCode) { |
||||||
193 | $event->setCoupon($order->couponCode); |
||||||
194 | } |
||||||
195 | |||||||
196 | // Add each line item in the transaction |
||||||
197 | // Two cases - variant and non variant products |
||||||
198 | $index = 1; |
||||||
199 | |||||||
200 | foreach ($order->lineItems as $lineItem) { |
||||||
201 | $this->addProductDataFromLineItem($event, $lineItem, $index); |
||||||
202 | $index++; |
||||||
203 | } |
||||||
204 | } |
||||||
205 | |||||||
206 | /** |
||||||
207 | * Add a Craft Commerce LineItem to an Analytics object |
||||||
208 | * |
||||||
209 | * @param ItemBaseEvent $event |
||||||
0 ignored issues
–
show
|
|||||||
210 | * @param LineItem $lineItem |
||||||
0 ignored issues
–
show
|
|||||||
211 | * @param int $index |
||||||
0 ignored issues
–
show
|
|||||||
212 | * @param string $listName |
||||||
0 ignored issues
–
show
|
|||||||
213 | * |
||||||
214 | * @return string the title of the product |
||||||
215 | * @throws InvalidConfigException |
||||||
216 | */ |
||||||
217 | protected function addProductDataFromLineItem(ItemBaseEvent $event, LineItem $lineItem, int $index = 0, string $listName = ''): string |
||||||
218 | { |
||||||
219 | $eventItem = $this->getNewItemParameter(); |
||||||
220 | |||||||
221 | $product = null; |
||||||
222 | $purchasable = $lineItem->purchasable; |
||||||
223 | |||||||
224 | /** @phpstan-ignore-next-line */ |
||||||
0 ignored issues
–
show
|
|||||||
225 | if ($purchasable === null) { |
||||||
226 | $eventItem->setItemName($lineItem->getDescription()); |
||||||
227 | $eventItem->setItemId($lineItem->getSku()); |
||||||
228 | } else { |
||||||
229 | $eventItem->setItemName($purchasable->title ?? $lineItem->getDescription()); |
||||||
230 | $eventItem->setItemId($purchasable->getSku()); |
||||||
231 | } |
||||||
232 | $eventItem->setPrice($lineItem->salePrice); |
||||||
233 | $eventItem->setQuantity($lineItem->qty); |
||||||
234 | |||||||
235 | // Handle this purchasable being a Variant |
||||||
236 | if (is_a($purchasable, Variant::class)) { |
||||||
237 | /** @var Variant $purchasable */ |
||||||
0 ignored issues
–
show
|
|||||||
238 | $product = $purchasable->getProduct(); |
||||||
0 ignored issues
–
show
The function
craft\commerce\elements\Variant::getProduct() has been deprecated: in 5.0.0. Use [[getOwner()]] instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
239 | $variant = $purchasable; |
||||||
240 | // Product with variants |
||||||
241 | $eventItem->setItemName($product->title); |
||||||
242 | $eventItem->setItemVariant($variant->title); |
||||||
243 | $eventItem->setItemCategory($product->getType()); |
||||||
244 | } |
||||||
245 | |||||||
246 | // Handle this purchasable being a Product |
||||||
247 | if (is_a($purchasable, Product::class)) { |
||||||
248 | /** @var Product $purchasable */ |
||||||
0 ignored issues
–
show
|
|||||||
249 | $product = $purchasable; |
||||||
250 | $eventItem->setItemName($product->title); |
||||||
251 | $eventItem->setItemVariant($product->title); |
||||||
252 | $eventItem->setItemCategory($product->getType()); |
||||||
253 | } |
||||||
254 | |||||||
255 | // Handle product lists |
||||||
256 | if ($index) { |
||||||
257 | $eventItem->setIndex($index); |
||||||
258 | } |
||||||
259 | |||||||
260 | if ($listName) { |
||||||
261 | $eventItem->setItemListName($listName); |
||||||
262 | } |
||||||
263 | |||||||
264 | // Add in any custom categories/brands that might be set |
||||||
265 | if (InstantAnalytics::$settings && $product) { |
||||||
266 | if (isset(InstantAnalytics::$settings['productCategoryField']) |
||||||
267 | && !empty(InstantAnalytics::$settings['productCategoryField'])) { |
||||||
0 ignored issues
–
show
|
|||||||
268 | $category = $this->pullDataFromField( |
||||||
269 | $product, |
||||||
270 | InstantAnalytics::$settings['productCategoryField'] |
||||||
271 | ); |
||||||
272 | $eventItem->setItemCategory($category); |
||||||
273 | } |
||||||
274 | if (isset(InstantAnalytics::$settings['productBrandField']) |
||||||
275 | && !empty(InstantAnalytics::$settings['productBrandField'])) { |
||||||
0 ignored issues
–
show
|
|||||||
276 | $brand = $this->pullDataFromField( |
||||||
277 | $product, |
||||||
278 | InstantAnalytics::$settings['productBrandField'] |
||||||
279 | ); |
||||||
280 | |||||||
281 | $eventItem->setItemBrand($brand); |
||||||
282 | } |
||||||
283 | } |
||||||
284 | |||||||
285 | //Add each product to the hit to be sent |
||||||
286 | $event->addItem($eventItem); |
||||||
287 | |||||||
288 | return $eventItem->getItemName(); |
||||||
0 ignored issues
–
show
|
|||||||
289 | } |
||||||
290 | |||||||
291 | /** |
||||||
0 ignored issues
–
show
|
|||||||
292 | * Extract product data from a Craft Commerce Product or Variant |
||||||
293 | * |
||||||
294 | * @param Product|Variant|null $productVariant the Product or Variant |
||||||
0 ignored issues
–
show
|
|||||||
295 | * |
||||||
296 | * @throws InvalidConfigException |
||||||
297 | */ |
||||||
0 ignored issues
–
show
|
|||||||
298 | protected function addProductDataFromProductOrVariant(ItemBaseEvent $event, $productVariant = null, $index = null, $listName = ''): void |
||||||
299 | { |
||||||
300 | if ($productVariant === null) { |
||||||
301 | return; |
||||||
302 | } |
||||||
303 | |||||||
304 | $eventItem = $this->getNewItemParameter(); |
||||||
305 | |||||||
306 | $isVariant = $productVariant instanceof Variant; |
||||||
307 | $variant = $isVariant ? $productVariant : $productVariant->getDefaultVariant(); |
||||||
308 | |||||||
309 | if (!$variant) { |
||||||
310 | return; |
||||||
311 | } |
||||||
312 | |||||||
313 | $eventItem->setItemId($variant->sku); |
||||||
314 | $eventItem->setItemName($variant->title); |
||||||
315 | $eventItem->setPrice((float)number_format($variant->price, 2, '.', '')); |
||||||
316 | |||||||
317 | $category = ($isVariant ? $variant->getProduct() : $productVariant)->getType()['name']; |
||||||
0 ignored issues
–
show
The method
getType() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() The function
craft\commerce\elements\Variant::getProduct() has been deprecated: in 5.0.0. Use [[getOwner()]] instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||
318 | |||||||
319 | if (InstantAnalytics::$settings) { |
||||||
320 | if (isset(InstantAnalytics::$settings['productCategoryField']) |
||||||
321 | && !empty(InstantAnalytics::$settings['productCategoryField'])) { |
||||||
0 ignored issues
–
show
|
|||||||
322 | $category = $this->pullDataFromField( |
||||||
323 | $productVariant, |
||||||
324 | InstantAnalytics::$settings['productCategoryField'] |
||||||
325 | ); |
||||||
326 | /* @TODO not sure what this even does |
||||||
327 | * if (empty($productData['category']) && $isVariant) { |
||||||
328 | * $category = $this->pullDataFromField( |
||||||
329 | * $productVariant->product, |
||||||
330 | * InstantAnalytics::$settings['productCategoryField'] |
||||||
331 | * ); |
||||||
332 | * } |
||||||
333 | */ |
||||||
334 | } |
||||||
335 | $eventItem->setItemCategory($category); |
||||||
336 | |||||||
337 | if (isset(InstantAnalytics::$settings['productBrandField']) |
||||||
338 | && !empty(InstantAnalytics::$settings['productBrandField'])) { |
||||||
0 ignored issues
–
show
|
|||||||
339 | $brand = $this->pullDataFromField( |
||||||
340 | $productVariant, |
||||||
341 | InstantAnalytics::$settings['productBrandField'], |
||||||
342 | true |
||||||
343 | ); |
||||||
344 | /* @TODO not sure what this even does |
||||||
345 | * if (empty($productData['brand']) && $isVariant) { |
||||||
346 | * $brand = $this->pullDataFromField( |
||||||
347 | * $productVariant, |
||||||
348 | * InstantAnalytics::$settings['productBrandField'], |
||||||
349 | * true |
||||||
350 | * ); |
||||||
351 | * } |
||||||
352 | */ |
||||||
353 | $eventItem->setItemBrand($brand); |
||||||
354 | } |
||||||
355 | } |
||||||
356 | |||||||
357 | if ($index !== null) { |
||||||
358 | $eventItem->setIndex($index); |
||||||
359 | } |
||||||
360 | |||||||
361 | if (!empty($listName)) { |
||||||
362 | $eventItem->setItemListName($listName); |
||||||
363 | } |
||||||
364 | |||||||
365 | // Add item info to the event |
||||||
366 | $event->addItem($eventItem); |
||||||
367 | } |
||||||
368 | |||||||
369 | /** |
||||||
0 ignored issues
–
show
|
|||||||
370 | * @param Product|Variant|null $productVariant |
||||||
0 ignored issues
–
show
|
|||||||
371 | * @param string $fieldHandle |
||||||
0 ignored issues
–
show
|
|||||||
372 | * @param bool $isBrand |
||||||
0 ignored issues
–
show
|
|||||||
373 | * |
||||||
374 | * @return string |
||||||
375 | */ |
||||||
376 | protected function pullDataFromField($productVariant, $fieldHandle, $isBrand = false): string |
||||||
377 | { |
||||||
378 | $result = ''; |
||||||
379 | if ($productVariant && $fieldHandle) { |
||||||
380 | $srcField = $productVariant[$fieldHandle] ?? $productVariant->product[$fieldHandle] ?? null; |
||||||
381 | // Handle eager loaded elements |
||||||
382 | if (is_array($srcField)) { |
||||||
383 | return $this->getDataFromElements($isBrand, $srcField); |
||||||
384 | } |
||||||
385 | // If the source field isn't an object, return nothing |
||||||
386 | if (!is_object($srcField)) { |
||||||
387 | return $result; |
||||||
388 | } |
||||||
389 | switch (get_class($srcField)) { |
||||||
390 | case TagQuery::class: |
||||||
0 ignored issues
–
show
|
|||||||
391 | break; |
||||||
392 | case CategoryQuery::class: |
||||||
0 ignored issues
–
show
|
|||||||
393 | case EntryQuery::class: |
||||||
0 ignored issues
–
show
|
|||||||
394 | $result = $this->getDataFromElements($isBrand, $srcField->all()); |
||||||
395 | break; |
||||||
396 | |||||||
397 | default: |
||||||
0 ignored issues
–
show
|
|||||||
398 | $result = strip_tags($srcField->__toString()); |
||||||
399 | break; |
||||||
400 | } |
||||||
401 | } |
||||||
402 | |||||||
403 | return $result; |
||||||
404 | } |
||||||
405 | |||||||
406 | /** |
||||||
0 ignored issues
–
show
|
|||||||
407 | * @param bool $isBrand |
||||||
0 ignored issues
–
show
|
|||||||
408 | * @param array $elements |
||||||
0 ignored issues
–
show
|
|||||||
409 | * @return string |
||||||
0 ignored issues
–
show
|
|||||||
410 | */ |
||||||
411 | protected function getDataFromElements(bool $isBrand, array $elements): string |
||||||
412 | { |
||||||
413 | $cats = []; |
||||||
414 | |||||||
415 | if ($isBrand) { |
||||||
416 | // Because we can only have one brand, we'll get |
||||||
417 | // the very last category. This means if our |
||||||
418 | // brand is a sub-category, we'll get the child |
||||||
419 | // not the parent. |
||||||
420 | foreach ($elements as $cat) { |
||||||
421 | $cats = [$cat->title]; |
||||||
422 | } |
||||||
423 | } else { |
||||||
424 | // For every category, show its ancestors |
||||||
425 | // delimited by a slash. |
||||||
426 | foreach ($elements as $cat) { |
||||||
427 | $name = $cat->title; |
||||||
428 | |||||||
429 | while ($cat = $cat->parent) { |
||||||
430 | $name = $cat->title . '/' . $name; |
||||||
431 | } |
||||||
432 | |||||||
433 | $cats[] = $name; |
||||||
434 | } |
||||||
435 | } |
||||||
436 | |||||||
437 | // Join separate categories with a pipe. |
||||||
438 | return implode('|', $cats); |
||||||
439 | } |
||||||
440 | |||||||
441 | /** |
||||||
442 | * Create an item parameter and set affiliation on it, if any exists. |
||||||
443 | * |
||||||
444 | * @return ItemParameter |
||||||
445 | */ |
||||||
446 | protected function getNewItemParameter(): ItemParameter |
||||||
447 | { |
||||||
448 | $parameter = new ItemParameter(); |
||||||
449 | $parameter->setAffiliation(InstantAnalytics::$plugin->ga4->getAnalytics()->getAffiliation()); |
||||||
450 | $parameter->setCurrency(CommercePlugin::getInstance()->getPaymentCurrencies()->getPrimaryPaymentCurrencyIso()); |
||||||
451 | |||||||
452 | return $parameter; |
||||||
453 | } |
||||||
454 | } |
||||||
455 |