Skip to content

Commit

Permalink
Merge pull request #41 from Setono/bot-detector
Browse files Browse the repository at this point in the history
Skip tracking for bot requests
  • Loading branch information
igormukhingmailcom authored Nov 19, 2021
2 parents 74dda1d + a3bb879 commit eddc140
Show file tree
Hide file tree
Showing 15 changed files with 217 additions and 145 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ in `config/bundles.php` file of your project before (!) `SyliusGridBundle`:
$bundles = [
Setono\ClientIdBundle\SetonoClientIdBundle::class => ['all' => true],
Setono\ConsentBundle\SetonoConsentBundle::class => ['all' => true],
Setono\BotDetectionBundle\SetonoBotDetectionBundle::class => ['all' => true],
Setono\SyliusFacebookPlugin\SetonoSyliusFacebookPlugin::class => ['all' => true],
Sylius\Bundle\GridBundle\SyliusGridBundle::class => ['all' => true],
];
Expand Down
3 changes: 2 additions & 1 deletion UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
1. As we're moving to server side tracking - we no longer need `SetonoTagBagBundle`
and `SetonoSyliusTagBagPlugin`.

- Remove them from `config/bundles.php`:
- Remove them from `config/bundles.php` and add ones we're using:

```diff
$bundles = [
- Setono\TagBagBundle\SetonoTagBagBundle::class => ['all' => true],
- Setono\SyliusTagBagPlugin\SetonoSyliusTagBagPlugin::class => ['all' => true],
+ Setono\ClientIdBundle\SetonoClientIdBundle::class => ['all' => true],
+ Setono\ConsentBundle\SetonoConsentBundle::class => ['all' => true],
+ Setono\BotDetectionBundle\SetonoBotDetectionBundle::class => ['all' => true],

Setono\SyliusFacebookPlugin\SetonoSyliusFacebookPlugin::class => ['all' => true],
Sylius\Bundle\GridBundle\SyliusGridBundle::class => ['all' => true],
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"fzaninotto/faker": "^1.6",
"knplabs/knp-menu": "^3.0",
"psr/log": "^1.1",
"setono/bot-detection-bundle": "^1.1",
"setono/client-id-bundle": "^0.2",
"setono/client-id-contracts": "^0.2",
"setono/consent-bundle": "^0.1",
Expand Down
71 changes: 27 additions & 44 deletions src/EventListener/AbstractSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,38 @@

namespace Setono\SyliusFacebookPlugin\EventListener;

use Doctrine\ORM\EntityManagerInterface;
use Setono\BotDetectionBundle\BotDetector\BotDetectorInterface;
use Setono\SyliusFacebookPlugin\Context\PixelContextInterface;
use Setono\SyliusFacebookPlugin\DataMapper\DataMapperInterface;
use Setono\SyliusFacebookPlugin\Factory\PixelEventFactoryInterface;
use Setono\SyliusFacebookPlugin\ServerSide\ServerSideEventFactoryInterface;
use Setono\SyliusFacebookPlugin\Generator\PixelEventsGeneratorInterface;
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

abstract class AbstractSubscriber implements EventSubscriberInterface
{
protected PixelContextInterface $pixelContext;

protected RequestStack $requestStack;

protected FirewallMap $firewallMap;

protected ServerSideEventFactoryInterface $serverSideFactory;

protected DataMapperInterface $dataMapper;
protected PixelContextInterface $pixelContext;

protected PixelEventFactoryInterface $pixelEventFactory;
protected PixelEventsGeneratorInterface $pixelEventsGenerator;

protected EntityManagerInterface $entityManager;
protected BotDetectorInterface $botDetector;

public function __construct(
PixelContextInterface $pixelContext,
RequestStack $requestStack,
FirewallMap $firewallMap,
ServerSideEventFactoryInterface $serverSideFactory,
DataMapperInterface $dataMapper,
PixelEventFactoryInterface $pixelEventFactory,
EntityManagerInterface $entityManager
PixelContextInterface $pixelContext,
PixelEventsGeneratorInterface $pixelEventsGenerator,
BotDetectorInterface $botDetector
) {
$this->pixelContext = $pixelContext;
$this->requestStack = $requestStack;
$this->firewallMap = $firewallMap;
$this->serverSideFactory = $serverSideFactory;
$this->dataMapper = $dataMapper;
$this->pixelEventFactory = $pixelEventFactory;
$this->entityManager = $entityManager;
}

protected function getMasterRequest(): ?Request
{
return $this->requestStack->getMasterRequest();
$this->pixelContext = $pixelContext;
$this->pixelEventsGenerator = $pixelEventsGenerator;
$this->botDetector = $botDetector;
}

protected function isShopContext(Request $request = null): bool
Expand All @@ -70,26 +55,24 @@ protected function isShopContext(Request $request = null): bool
return $firewallConfig->getName() === 'shop';
}

/**
* @param object $source
*/
protected function generatePixelEvents($source, string $eventName, Request $request = null): void
protected function isRequestEligible(): bool
{
$serverSideEvent = $this->serverSideFactory->create($eventName);
$this->dataMapper->map($source, $serverSideEvent, [
'request' => $request ?? $this->getMasterRequest(),
'event' => $eventName,
]);

$pixels = $this->pixelContext->getPixels();
foreach ($pixels as $pixel) {
// @todo Maybe its better to just clone
$pixelEvent = $this->pixelEventFactory->createFromServerSideEvent($serverSideEvent);
$pixelEvent->setPixel($pixel);

$this->entityManager->persist($pixelEvent);
// As one main request can have multiple subrequests
// we don't want things to be tracked multiple times
// So, having in mind that `If current Request is the master request, it returns null`
// we expect getParentRequest to be null to proceed
if (null !== $this->requestStack->getParentRequest()) {
return false;
}

if (!$this->isShopContext()) {
return false;
}

if ($this->botDetector->isBotRequest()) {
return false;
}

$this->entityManager->flush();
return true;
}
}
26 changes: 10 additions & 16 deletions src/EventListener/AddToCartSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@

namespace Setono\SyliusFacebookPlugin\EventListener;

use Doctrine\ORM\EntityManagerInterface;
use Setono\BotDetectionBundle\BotDetector\BotDetectorInterface;
use Setono\SyliusFacebookPlugin\Context\PixelContextInterface;
use Setono\SyliusFacebookPlugin\DataMapper\DataMapperInterface;
use Setono\SyliusFacebookPlugin\Factory\PixelEventFactoryInterface;
use Setono\SyliusFacebookPlugin\ServerSide\ServerSideEventFactoryInterface;
use Setono\SyliusFacebookPlugin\Generator\PixelEventsGeneratorInterface;
use Setono\SyliusFacebookPlugin\ServerSide\ServerSideEventInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Order\Context\CartContextInterface;
Expand All @@ -20,23 +18,19 @@ final class AddToCartSubscriber extends AbstractSubscriber
protected CartContextInterface $cartContext;

public function __construct(
PixelContextInterface $pixelContext,
RequestStack $requestStack,
FirewallMap $firewallMap,
ServerSideEventFactoryInterface $serverSideFactory,
DataMapperInterface $dataMapper,
PixelEventFactoryInterface $pixelEventFactory,
EntityManagerInterface $entityManager,
PixelContextInterface $pixelContext,
PixelEventsGeneratorInterface $pixelEventsGenerator,
BotDetectorInterface $botDetector,
CartContextInterface $cartContext
) {
parent::__construct(
$pixelContext,
$requestStack,
$firewallMap,
$serverSideFactory,
$dataMapper,
$pixelEventFactory,
$entityManager
$pixelContext,
$pixelEventsGenerator,
$botDetector
);

$this->cartContext = $cartContext;
Expand All @@ -53,7 +47,7 @@ public static function getSubscribedEvents(): array

public function track(): void
{
if (!$this->isShopContext() || !$this->pixelContext->hasPixels()) {
if (!$this->isRequestEligible() || !$this->pixelContext->hasPixels()) {
return;
}

Expand All @@ -62,7 +56,7 @@ public function track(): void
return;
}

$this->generatePixelEvents(
$this->pixelEventsGenerator->generatePixelEvents(
$order,
ServerSideEventInterface::EVENT_ADD_TO_CART
);
Expand Down
59 changes: 28 additions & 31 deletions src/EventListener/InitiateCheckoutSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@

namespace Setono\SyliusFacebookPlugin\EventListener;

use Doctrine\ORM\EntityManagerInterface;
use Setono\BotDetectionBundle\BotDetector\BotDetectorInterface;
use Setono\SyliusFacebookPlugin\Context\PixelContextInterface;
use Setono\SyliusFacebookPlugin\DataMapper\DataMapperInterface;
use Setono\SyliusFacebookPlugin\Factory\PixelEventFactoryInterface;
use Setono\SyliusFacebookPlugin\ServerSide\ServerSideEventFactoryInterface;
use Setono\SyliusFacebookPlugin\Generator\PixelEventsGeneratorInterface;
use Setono\SyliusFacebookPlugin\ServerSide\ServerSideEventInterface;
use Sylius\Component\Order\Context\CartContextInterface;
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
Expand All @@ -21,23 +19,19 @@ final class InitiateCheckoutSubscriber extends AbstractSubscriber
protected CartContextInterface $cartContext;

public function __construct(
PixelContextInterface $pixelContext,
RequestStack $requestStack,
FirewallMap $firewallMap,
ServerSideEventFactoryInterface $serverSideFactory,
DataMapperInterface $dataMapper,
PixelEventFactoryInterface $pixelEventFactory,
EntityManagerInterface $entityManager,
PixelContextInterface $pixelContext,
PixelEventsGeneratorInterface $pixelEventsGenerator,
BotDetectorInterface $botDetector,
CartContextInterface $cartContext
) {
parent::__construct(
$pixelContext,
$requestStack,
$firewallMap,
$serverSideFactory,
$dataMapper,
$pixelEventFactory,
$entityManager
$pixelContext,
$pixelEventsGenerator,
$botDetector
);

$this->cartContext = $cartContext;
Expand All @@ -52,18 +46,7 @@ public static function getSubscribedEvents(): array

public function track(RequestEvent $requestEvent): void
{
$request = $requestEvent->getRequest();

if (!$requestEvent->isMasterRequest()) {
return;
}

if (!$request->attributes->has('_route')) {
return;
}

$route = $request->attributes->get('_route');
if ('sylius_shop_checkout_start' !== $route) {
if (!$this->isRequestEligible() || !$this->pixelContext->hasPixels()) {
return;
}

Expand All @@ -72,13 +55,27 @@ public function track(RequestEvent $requestEvent): void
return;
}

if (!$this->pixelContext->hasPixels()) {
return;
}

$this->generatePixelEvents(
$this->pixelEventsGenerator->generatePixelEvents(
$cart,
ServerSideEventInterface::EVENT_INITIATE_CHECKOUT
);
}

/**
* Request is eligible when:
* - We are on the 'checkout start' page
*/
protected function isRequestEligible(): bool
{
if (!parent::isRequestEligible()) {
return false;
}

$request = $this->requestStack->getCurrentRequest();
if (null === $request) {
return false;
}

return 'sylius_shop_checkout_start' === $request->attributes->get('_route');
}
}
Loading

0 comments on commit eddc140

Please sign in to comment.