src/JanusHercules/ConversionEventTracking/Presentation/EventSubscriber/Step1TrackingSubscriber.php line 52

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace JanusHercules\ConversionEventTracking\Presentation\EventSubscriber;
  4. use App\Entity\ConversionEvent;
  5. use App\Service\ConversionEventService;
  6. use App\Service\SessionService;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use Exception;
  9. use JanusHercules\ConversionEventTracking\Domain\Dto\CampaignSubcampaignPairDto;
  10. use JanusHercules\ConversionEventTracking\Presentation\Service\Step0SessionServiceInterface;
  11. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  12. use Symfony\Component\HttpKernel\Event\RequestEvent;
  13. use Symfony\Component\HttpKernel\KernelEvents;
  14. /**
  15. * Event Subscriber für Step 1 Tracking (Link Clicked).
  16. *
  17. * Erkennt den __ggcts1 URL-Parameter und erstellt Step 1 Events
  18. * für alle enthaltenen Campaign/Subcampaign-Paare.
  19. *
  20. * @see https://github.com/joboo-gmbh/joboo-marketing/blob/main/docs/outbound-url-tracking.md
  21. */
  22. final class Step1TrackingSubscriber implements EventSubscriberInterface
  23. {
  24. /**
  25. * URL-Parameter für Step 1 Tracking.
  26. * __ggcts1 = go-gastro Conversion Tracking Step 1.
  27. */
  28. private const PARAM_NAME = '__ggcts1';
  29. public function __construct(
  30. private readonly ConversionEventService $conversionEventService,
  31. private readonly SessionService $sessionService,
  32. private readonly Step0SessionServiceInterface $step0SessionService,
  33. private readonly EntityManagerInterface $entityManager
  34. ) {
  35. }
  36. public static function getSubscribedEvents(): array
  37. {
  38. return [
  39. KernelEvents::REQUEST => 'onKernelRequest',
  40. ];
  41. }
  42. /**
  43. * @throws Exception
  44. */
  45. public function onKernelRequest(RequestEvent $event): void
  46. {
  47. if (!$event->isMainRequest()) {
  48. return;
  49. }
  50. $request = $event->getRequest();
  51. $paramValue = $request->query->get(self::PARAM_NAME);
  52. if (empty($paramValue) || !is_string($paramValue)) {
  53. return;
  54. }
  55. $session = $request->getSession();
  56. if (!$session->isStarted()) {
  57. return;
  58. }
  59. $step0EventIds = $this->step0SessionService->getAllStep0EventIds($session);
  60. // Parse: "117:0,118:0" → [CampaignSubcampaignPairDto(117, 0), CampaignSubcampaignPairDto(118, 0)]
  61. $pairs = CampaignSubcampaignPairDto::parseFromUrlParam($paramValue);
  62. foreach ($pairs as $pair) {
  63. $sessionKey = $pair->getSessionKey();
  64. $step0EventId = $step0EventIds[$sessionKey] ?? null;
  65. if ($step0EventId !== null) {
  66. // Step 0 Event aus DB laden
  67. /** @var ConversionEvent|null $step0Event */
  68. $step0Event = $this->entityManager->find(ConversionEvent::class, $step0EventId);
  69. if ($step0Event !== null) {
  70. // Step 1 Event erstellen (referenziert auf Step 0)
  71. $step1Event = $this->conversionEventService->createStepLinkClickedConversionEvent(
  72. $step0Event,
  73. $request
  74. );
  75. // Step 1 Event-ID für Goal-Tracking speichern
  76. $this->sessionService->addConversionEventId(
  77. $session,
  78. $step1Event->getId(),
  79. $pair->campaignId,
  80. $pair->subcampaignId,
  81. null
  82. );
  83. }
  84. // Step 0 aus Session entfernen (wurde verarbeitet)
  85. unset($step0EventIds[$sessionKey]);
  86. } else {
  87. // Fallback: Kein Step 0 vorhanden (z.B. JS war deaktiviert)
  88. // → Step 0 + Step 1 zusammen erstellen
  89. $this->conversionEventService->initiateGoalReachedConversionTracking(
  90. null,
  91. $pair->campaignId,
  92. $pair->subcampaignId,
  93. null,
  94. $request
  95. );
  96. }
  97. }
  98. // Aktualisierte Step 0 IDs zurückschreiben:
  99. // Die Session kann mehrere Step 0 Event-IDs enthalten (z.B. wenn der User mehrere
  100. // Landingpages besucht hat). Oben wurden nur die Step 0 IDs verarbeitet, die im
  101. // URL-Parameter __ggcts1 referenziert wurden – diese wurden via unset() aus dem
  102. // Array entfernt. Hier schreiben wir das bereinigte Array zurück, damit:
  103. // 1. Verarbeitete Step 0 IDs nicht erneut zu Step 1 konvertiert werden (F5/Zurück)
  104. // 2. Nicht-verarbeitete Step 0 IDs für spätere Klicks erhalten bleiben
  105. $this->step0SessionService->setAllStep0EventIds($session, $step0EventIds);
  106. // Parameter aus Request entfernen (für saubere URLs in Logs etc.)
  107. $request->query->remove(self::PARAM_NAME);
  108. }
  109. }