20 public const ID =
'id';
21 public const IDS =
'ids';
22 public const NAME =
'name';
33 if (!self::isAllowedRegion())
38 $request = \Bitrix\Main\Context::getCurrent()->getRequest();
39 $action = $request->get(
'action');
40 if ($action !==
'ADD2BASKET' && $action !==
'BUY')
45 if (!self::checkClass())
50 $params = self::getFacebookConversionParams(Facebook\Event::EVENT_ADD_TO_CART);
56 if ($params[self::ID] !==
'Y')
62 'content_type' =>
'product',
65 if ($params[self::NAME] ===
'Y')
67 $customDataParams[
'content_name'] = $productData[
'NAME'];
69 if ($params[self::GROUP] ===
'Y')
71 $customDataParams[
'content_category'] = self::getProductDeepestSection((
int)$productData[
'PRODUCT_ID']);
73 if ($params[self::PRICE] ===
'Y')
75 $customDataParams[
'value'] = $productData[
'PRICE'];
76 $customDataParams[
'currency'] = $productData[
'CURRENCY'];
78 if ($params[self::QUANTITY] ===
'Y')
80 $customDataParams[
'contents'] = [
82 'product_id' => $productData[
'PRODUCT_ID'],
83 'quantity' => $productData[
'QUANTITY'],
89 $customDataParams[
'content_ids'] = [$productData[
'PRODUCT_ID']];
92 self::fireEvent(Facebook\Event::EVENT_ADD_TO_CART, $customDataParams);
95 public static function onOrderCreatedHandler(
Order $order): void
97 if (!self::isAllowedRegion())
102 $application = \Bitrix\Main\Application::getInstance();
103 $session = $application ? $application->getSession() :
null;
104 $isInitiateCheckoutSent =
106 ? $session->has(
'FACEBOOK_CONVERSION_INITIATE_CHECKOUT_SENT_' . SITE_ID)
112 $isInitiateCheckoutSent
116 $session->remove(
'FACEBOOK_CONVERSION_INITIATE_CHECKOUT_SENT_' . SITE_ID);
121 if ($isInitiateCheckoutSent)
125 $session->set(
'FACEBOOK_CONVERSION_INITIATE_CHECKOUT_SENT_' . SITE_ID,
true);
127 if (!self::checkClass())
132 $params = self::getFacebookConversionParams(Facebook\Event::EVENT_INITIATE_CHECKOUT);
138 if ($params[self::IDS] !==
'Y')
143 $customDataParams = self::getCustomDataParamsForOrderEvent($order, $params);
145 if ($params[self::QUANTITY] ===
'Y')
149 foreach ($order->getBasket()->getBasketItems() as $basketItem)
151 $totalQuantity += $basketItem->getQuantity();
153 $customDataParams[
'num_items'] = (int)$totalQuantity;
156 self::fireEvent(Facebook\Event::EVENT_INITIATE_CHECKOUT, $customDataParams);
159 public static function onOrderSavedHandler(\
Bitrix\Main\Event $event): void
161 if (!self::isAllowedRegion())
172 $order = $event->getParameter(
'ENTITY');
178 if (!self::checkClass())
183 $params = self::getFacebookConversionParams(Facebook\Event::EVENT_ADD_PAYMENT);
189 if ($params[self::IDS] !==
'Y')
194 $customDataParams = self::getCustomDataParamsForOrderEvent($order, $params);
196 self::fireEvent(Facebook\Event::EVENT_ADD_PAYMENT, $customDataParams);
199 public static function getCustomDataParamsForOrderEvent(Order $order, array $params): array
201 $customDataParams = [
202 'content_type' =>
'product',
205 if ($params[self::PRODUCTS_GROUP_AND_QUANTITY] ===
'Y')
208 foreach ($order->getBasket()->getBasketItems() as $basketItem)
212 'product_id' => $basketItem->getProductId(),
213 'category' => self::getProductDeepestSection((
int)$basketItem->getProductId()),
214 'quantity' => $basketItem->getQuantity(),
217 $customDataParams[
'contents'] = $products;
222 foreach ($order->getBasket()->getBasketItems() as $basketItem)
225 $productIds[] = $basketItem->getProductId();
227 $customDataParams[
'content_ids'] = $productIds;
230 if ($params[self::PRICE] ===
'Y')
232 $customDataParams[
'value'] = $order->getPrice();
233 $customDataParams[
'currency'] = $order->getCurrency();
236 return $customDataParams;
241 if (!self::isAllowedRegion())
246 $email = $event->getParameter(
'AUTHOR_EMAIL') ??
'';
247 self::fireContactEvent(self::EMAIL, (
string)$email);
252 if (!self::isAllowedRegion())
259 if (is_array($contactBy))
261 $type = $contactBy[
'type'] ??
'';
262 $value = $contactBy[
'value'] ??
'';
270 self::fireContactEvent((
string)$type, (
string)$value);
273 private static function fireContactEvent(
string $type,
string $value): void
275 if (!self::checkClass())
280 $params = self::getFacebookConversionParams(Facebook\Event::EVENT_CONTACT);
286 if (!isset($params[$type]) || $params[$type] !==
'Y')
291 $customDataParams[
'content_name'] = $value;
293 self::fireEvent(Facebook\Event::EVENT_CONTACT, $customDataParams);
298 if (!self::isAllowedRegion())
303 if (!self::checkClass())
308 $params = self::getFacebookConversionParams(Facebook\Event::EVENT_DONATE);
314 if ($params[self::ID] !==
'Y')
319 $customDataParams = [
320 'content_type' =>
'product',
321 'content_ids' => [$offerId],
324 if ($params[self::NAME_AND_PROPERTIES] ===
'Y')
326 $skuPropertiesTextValue = self::getSkuNameAndPropertiesTextValue($offerId);
327 if ($skuPropertiesTextValue)
329 $customDataParams[
'content_name'] = $skuPropertiesTextValue;
333 self::fireEvent(Facebook\Event::EVENT_DONATE, $customDataParams);
336 private static function getSkuNameAndPropertiesTextValue(
int $offerId): ?string
339 $skuEntity = ServiceContainer::getRepositoryFacade()->loadVariation($offerId);
345 $skuTree = self::getProductSkuTree($skuEntity);
351 $selectedValues = $skuTree[
'SELECTED_VALUES'];
352 $offersProp = $skuTree[
'OFFERS_PROP'];
355 foreach ($offersProp as $property)
357 $selectedValueId = $selectedValues[$property[
'ID']];
358 if ($selectedValueId === 0)
363 $filteredValues = array_filter(
365 static function($valuesElement) use($selectedValueId) {
366 return $valuesElement[
'ID'] === $selectedValueId;
369 $skuProperties[] = $filteredValues[array_key_first($filteredValues)][
'NAME'];
372 return $skuEntity->getName() .
' ' . implode(
', ', $skuProperties);
375 private static function getProductSkuTree(BaseSku $skuEntity): ?array
378 $skuTreeComponent = ServiceContainer::make(
'sku.tree', [
'iblockId' => $skuEntity->getIblockId()]);
379 if (!$skuTreeComponent)
385 $productEntity = $skuEntity->getParent();
392 $skuIds = array_column($productEntity->getSkuCollection()->toArray(),
'ID');
393 $productsSkuTree = $skuTreeComponent->loadWithSelectedOffers(
394 [$productId => $skuIds]
397 return $productsSkuTree[
$productId][$skuEntity->getId()];
400 private static function fireEvent(
string $eventName, array $customDataParams): void
402 $conversion = self::getConversionEntity($eventName, $customDataParams);
405 function() use ($conversion, $eventName) {
408 $isEventSent = $conversion->fireEvents();
411 $analyticsEvent =
new Analytics\Events\Event(
412 Analytics\Events\Event::FACEBOOK_CONVERSION_EVENT_FIRED,
414 'EVENT_NAME' => $eventName,
418 $provider =
new Analytics\Events\Provider($analyticsEvent);
419 (
new Analytics\Storage($provider))->
save();
422 catch (\Throwable $throwable)
429 private static function getConversionEntity(
431 array $customDataParams
432 ): ?Facebook\Conversion
434 $service = self::getService();
440 $customData =
new Facebook\CustomData($customDataParams);
441 $userData =
new Facebook\UserData([
442 'client_ip_address' => $_SERVER[
'REMOTE_ADDR'],
443 'client_user_agent' => $_SERVER[
'HTTP_USER_AGENT'],
445 $event =
new Facebook\Event([
446 'event_name' => $eventName,
447 'custom_data' => $customData,
448 'user_data' => $userData,
449 'event_source_url' => self::getSiteUrl(),
451 $conversion =
new Facebook\Conversion($service);
452 $conversion->addEvent($event);
457 private static function getSiteUrl(): string
465 $request = \Bitrix\Main\Context::getCurrent()->getRequest();
466 $protocol = $request->isHttps() ?
'https://' :
'http://';
467 $url = $protocol . $request->getHttpHost();
469 $site = \Bitrix\Main\SiteTable::getList([
470 'select' => [
'LID',
'DIR'],
475 'cache' => [
'ttl' => 86400],
479 $url .= $site[
'DIR'];
485 private static function getProductDeepestSection(
int $productId):? string
488 $variation = ServiceContainer::getRepositoryFacade()->loadVariation($productId);
495 $product = $variation->getParent();
501 $sectionIds = $product->getSectionCollection()->getValues();
502 if (!empty($sectionIds))
504 $sectionData = \CIBlockSection::GetList(
505 [
'DEPTH_LEVEL' =>
'DESC'],
506 [
'ID' => $sectionIds],
512 return $sectionData[
'NAME'];
519 private static function checkClass(): bool
521 return self::checkModules() && self::getService();
524 private static function checkModules(): bool
527 Loader::includeModule(
'seo')
528 && Loader::includeModule(
'socialservices')
529 && Loader::includeModule(
'sale')
533 private static function getService(): ?Service
535 return ServiceLocator::getInstance()->get(
'seo.business.service') ?:
null;
538 private static function getFacebookConversionParamsData(
string $eventName):? array
540 $facebookConversionParamsData = FacebookConversionParamsTable::getList([
542 '=EVENT_NAME' => $eventName,
548 return $facebookConversionParamsData ?:
null;
551 private static function getFacebookConversionParams(
string $eventName): ?array
553 $facebookConversionParamsData = self::getFacebookConversionParamsData($eventName);
554 if (!$facebookConversionParamsData || $facebookConversionParamsData[
'ENABLED'] !==
'Y')
559 $params = unserialize($facebookConversionParamsData[
'PARAMS'], [
'allowed_classes' =>
false]);
568 private static function isAllowedRegion(): bool
570 $region = \Bitrix\Main\Application::getInstance()->getLicense()->getRegion();
572 return $region !==
null && $region !==
'ru';
577 if (!self::isAllowedRegion())
582 static $isEventEnabled;
583 if (isset($isEventEnabled[$eventName]))
585 return $isEventEnabled[$eventName];
588 $facebookConversionParams = self::getFacebookConversionParamsData($eventName);
589 $isEventEnabled[$eventName] =
590 isset($facebookConversionParams[
'ENABLED']) && $facebookConversionParams[
'ENABLED'] ===
'Y'
593 return $isEventEnabled[$eventName];
598 $facebookConversionParamsResult = FacebookConversionParamsTable::getList([
603 while ($facebookConversionParams = $facebookConversionParamsResult->fetch())
605 FacebookConversionParamsTable::delete($facebookConversionParams[
'ID']);