src/Event/UtmSubscriber.php line 21

Open in your IDE?
  1. <?php
  2. /**
  3.  * @author Antony Tkachenko <at@canaryknight.ru>
  4.  */
  5. namespace App\Event;
  6. use App\Utm\Utm;
  7. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  8. use Symfony\Component\HttpFoundation\Cookie;
  9. use Symfony\Component\HttpKernel\Event\RequestEvent;
  10. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  11. use Symfony\Component\HttpKernel\KernelEvents;
  12. class UtmSubscriber implements EventSubscriberInterface
  13. {
  14.     const UTM_COOKIE_NAME 'gmb_campaign';
  15.     private $setCookie false;
  16.     public function parseUtm(RequestEvent $event)
  17.     {
  18.         if (!$event->isMainRequest()) {
  19.             return;
  20.         }
  21.         $request $event->getRequest();
  22.         $request->attributes->set(self::UTM_COOKIE_NAMEUtm::fromArray([]));
  23.         $value $request->cookies->get(self::UTM_COOKIE_NAME'[]');
  24.         try {
  25.             $data json_decode($valuetrueJSON_THROW_ON_ERROR);
  26.         } catch (\Throwable $e) {
  27.             $data = [];
  28.         }
  29.         if (!empty($data)) {
  30.             // utm cookie already set
  31.             $request->attributes->set(self::UTM_COOKIE_NAMEUtm::fromArray($data));
  32.             return;
  33.         }
  34.         $values = [];
  35.         foreach (Utm::PARAMS as $param) {
  36.             if (!$request->query->has($param)) {
  37.                 continue;
  38.             }
  39.             $values[$param] = (string) $request->query->get($param);
  40.         }
  41.         [$referrer$source] = $this->parseReferrer((string) $request->headers->get('referer'));
  42.         if ($referrer) {
  43.             $values['referrer'] = $referrer;
  44.         }
  45.         $values['utm_source'] = $values['utm_source'] ?? $source;
  46.         $utm Utm::fromArray($values);
  47.         $request->attributes->set(self::UTM_COOKIE_NAME$utm);
  48.         if (!empty($values)) {
  49.             $this->setCookie true;
  50.         }
  51.     }
  52.     public function saveUtm(ResponseEvent $event)
  53.     {
  54.         if (!$this->setCookie) {
  55.             return;
  56.         }
  57.         $response $event->getResponse();
  58.         $request $event->getRequest();
  59.         if (!$request->attributes->has(self::UTM_COOKIE_NAME)) {
  60.             return;
  61.         }
  62.         $value json_encode($request->attributes->get(self::UTM_COOKIE_NAME));
  63.         $cookie Cookie::create(self::UTM_COOKIE_NAME)
  64.             ->withValue($value)
  65.             ->withExpires(strtotime("+1 year"))
  66.             ->withDomain('.'.$event->getRequest()->getHost())
  67.         ;
  68.         $response->headers->setCookie($cookie);
  69.     }
  70.     private function parseReferrer(string $referrer)
  71.     {
  72.         if (empty($referrer)) {
  73.             return [null'direct'];
  74.         }
  75.         $host parse_url($referrerPHP_URL_HOST);
  76.         if (false === $host) {
  77.             // not valid url
  78.             return [nullnull];
  79.         }
  80.         $hostNames =  (array) explode("."mb_strtolower($host));
  81.         $count count($hostNames);
  82.         if ($count 2) {
  83.             return [$hostnull];
  84.         }
  85.         $tld $hostNames[$count-2] . '.' $hostNames[$count-1];
  86.         if (in_array($tld, ['getmeback.ru''getmeback.io'], true)) {
  87.             return [null'direct'];
  88.         }
  89.         $searchEngines = [
  90.             'google.com',
  91.             'yandex.ru',
  92.             'mail.ru',
  93.             'rambler.ru',
  94.             'duckduckgo.com',
  95.             'yahoo.com',
  96.             'bing.com',
  97.             'baidu.com',
  98.         ];
  99.         $source in_array($tld$searchEnginestrue) ? 'organic' null;
  100.         return [$tld$source];
  101.     }
  102.     public static function getSubscribedEvents()
  103.     {
  104.         return [
  105.             KernelEvents::REQUEST => 'parseUtm',
  106.             KernelEvents::RESPONSE => 'saveUtm',
  107.         ];
  108.     }
  109. }