Skip to content

Commit

Permalink
[FEATURE] Add push service in JavaScript for virtual page visits and …
Browse files Browse the repository at this point in the history
…searches

On some pages with multiple pages that do only exist via JavaScript or for sliders, accordions, etc... it can be useful to push an individual path via JavaScript. That can be done now via:
```
const lux = LuxSingleton.getInstance();
lux.push('page/step1', 'virtualPageRequest');
```

With the same commit, we can now also push searchterms via JavaScript. This is helpful if the searchword is not delivered as GET parameter (e.g. with an AJAX searchresult page, etc...). This can be done now via:
```
const lux = LuxSingleton.getInstance();
lux.push('any searchterm', 'searchRequest');
```
  • Loading branch information
einpraegsam committed Jul 26, 2024
1 parent 94b976f commit 5361d91
Show file tree
Hide file tree
Showing 20 changed files with 274 additions and 64 deletions.
115 changes: 85 additions & 30 deletions Classes/Controller/FrontendController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Doctrine\DBAL\Exception as ExceptionDbal;
use In2code\Lux\Domain\Factory\VisitorFactory;
use In2code\Lux\Domain\Model\Visitor;
use In2code\Lux\Domain\Repository\PagevisitRepository;
use In2code\Lux\Domain\Service\ConfigurationService;
use In2code\Lux\Domain\Service\Email\SendAssetEmail4LinkService;
use In2code\Lux\Domain\Tracker\AbTestingTracker;
Expand All @@ -19,6 +20,7 @@
use In2code\Lux\Domain\Tracker\NewsTracker;
use In2code\Lux\Domain\Tracker\PageTracker;
use In2code\Lux\Domain\Tracker\SearchTracker;
use In2code\Lux\Domain\Tracker\VirtualPageTracker;
use In2code\Lux\Events\AfterTrackingEvent;
use In2code\Lux\Exception\ActionNotAllowedException;
use In2code\Lux\Exception\ConfigurationException;
Expand All @@ -41,11 +43,44 @@

class FrontendController extends ActionController
{
protected ConfigurationService $configurationService;
protected CompanyTracker $companyTracker;
protected PageTracker $pageTracker;
protected VirtualPageTracker $virtualPageTracker;
protected NewsTracker $newsTracker;
protected SearchTracker $searchTracker;
protected $eventDispatcher;
protected LoggerInterface $logger;
protected array $allowedActions = [
'pageRequest',
'virtualPageRequest',
'searchRequest',
'fieldListeningRequest',
'formListeningRequest',
'email4LinkRequest',
'downloadRequest',
'linkClickRequest',
'redirectRequest',
'abTestingRequest',
'abTestingConversionFulfilledRequest',
];

public function __construct(EventDispatcherInterface $eventDispatcher, LoggerInterface $logger)
{
public function __construct(
ConfigurationService $configurationService,
CompanyTracker $companyTracker,
PageTracker $pageTracker,
VirtualPageTracker $virtualPageTracker,
NewsTracker $newsTracker,
SearchTracker $searchTracker,
EventDispatcherInterface $eventDispatcher,
LoggerInterface $logger
) {
$this->configurationService = $configurationService;
$this->companyTracker = $companyTracker;
$this->pageTracker = $pageTracker;
$this->virtualPageTracker = $virtualPageTracker;
$this->newsTracker = $newsTracker;
$this->searchTracker = $searchTracker;
$this->eventDispatcher = $eventDispatcher;
$this->logger = $logger;
}
Expand All @@ -57,19 +92,8 @@ public function __construct(EventDispatcherInterface $eventDispatcher, LoggerInt
*/
public function initializeDispatchRequestAction(): void
{
$allowedActions = [
'pageRequest',
'fieldListeningRequest',
'formListeningRequest',
'email4LinkRequest',
'downloadRequest',
'linkClickRequest',
'redirectRequest',
'abTestingRequest',
'abTestingConversionFulfilledRequest',
];
$action = $this->request->getArgument('dispatchAction');
if (!in_array($action, $allowedActions)) {
if (!in_array($action, $this->allowedActions)) {
throw new ActionNotAllowedException('Action not allowed', 1518815149);
}
}
Expand All @@ -87,8 +111,7 @@ public function dispatchRequestAction(
string $identificator,
array $arguments
): ResponseInterface {
$configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
if ($configurationService->getTypoScriptSettingsByPath('general.enable') !== '0') {
if ($this->configurationService->getTypoScriptSettingsByPath('general.enable') !== '0') {
return (new ForwardResponse($dispatchAction))
->withArguments(['identificator' => $identificator, 'arguments' => $arguments]);
}
Expand All @@ -106,14 +129,50 @@ public function pageRequestAction(string $identificator, array $arguments): Resp
try {
$visitor = $this->getVisitor($identificator);
$this->callAdditionalTrackers($visitor, $arguments);
$companyTracker = GeneralUtility::makeInstance(CompanyTracker::class);
$companyTracker->track($visitor);
$pageTracker = GeneralUtility::makeInstance(PageTracker::class);
$pagevisit = $pageTracker->track($visitor, $arguments);
$newsTracker = GeneralUtility::makeInstance(NewsTracker::class);
$newsTracker->track($visitor, $arguments, $pagevisit);
$searchTracker = GeneralUtility::makeInstance(SearchTracker::class);
$searchTracker->track($visitor, $arguments, $pagevisit);
$this->companyTracker->track($visitor);
$pagevisit = $this->pageTracker->track($visitor, $arguments);
$this->newsTracker->track($visitor, $arguments, $pagevisit);
$this->searchTracker->track($visitor, $arguments, $pagevisit);
return $this->jsonResponse(json_encode($this->afterAction($visitor)));
} catch (Throwable $exception) {
return $this->jsonResponse(json_encode($this->getError($exception)));
}
}

/**
* Is typically called manually in own JavaScript
*
* @param string $identificator
* @param array $arguments
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function virtualPageRequestAction(string $identificator, array $arguments): ResponseInterface
{
try {
$visitor = $this->getVisitor($identificator);
$this->virtualPageTracker->track($visitor, $arguments);
return $this->jsonResponse(json_encode($this->afterAction($visitor)));
} catch (Throwable $exception) {
return $this->jsonResponse(json_encode($this->getError($exception)));
}
}

/**
* Is typically called manually in own JavaScript
*
* @param string $identificator
* @param array $arguments
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function searchRequestAction(string $identificator, array $arguments): ResponseInterface
{
try {
$visitor = $this->getVisitor($identificator);
$pagevisitRepository = GeneralUtility::makeInstance(PagevisitRepository::class);
$pagevisit = $pagevisitRepository->findByUid((int)$arguments['pageUid']);
$this->searchTracker->track($visitor, $arguments, $pagevisit);
return $this->jsonResponse(json_encode($this->afterAction($visitor)));
} catch (Throwable $exception) {
return $this->jsonResponse(json_encode($this->getError($exception)));
Expand Down Expand Up @@ -389,17 +448,13 @@ protected function callAdditionalTrackers(Visitor $visitor, array $arguments): v
protected function afterAction(Visitor $visitor): array
{
/** @var AfterTrackingEvent $event */
$event = $this->eventDispatcher->dispatch(
GeneralUtility::makeInstance(AfterTrackingEvent::class, $visitor, $this->actionMethodName)
);
$event = $this->eventDispatcher->dispatch(new AfterTrackingEvent($visitor, $this->actionMethodName));
return $event->getResults();
}

protected function getError(Throwable $exception): array
{
$this->eventDispatcher->dispatch(
GeneralUtility::makeInstance(AfterTrackingEvent::class, new Visitor(), 'error', ['error' => $exception])
);
$this->eventDispatcher->dispatch(new AfterTrackingEvent(new Visitor(), 'error', ['error' => $exception]));
if (BackendUtility::isBackendAuthentication() === false) {
// Log error to var/log/typo3_[hash].log
$this->logger->warning('Error in FrontendController happened', [
Expand Down
12 changes: 12 additions & 0 deletions Classes/Domain/LogEventListeners/Log.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use In2code\Lux\Events\Log\LogVisitorIdentifiedByLuxletterlinkEvent;
use In2code\Lux\Events\Log\SearchEvent;
use In2code\Lux\Events\Log\UtmEvent;
use In2code\Lux\Events\Log\VirtualPageTrackerEvent;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;
use TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException;
Expand Down Expand Up @@ -121,6 +122,17 @@ public function logEmail4LinkEmailFailed(LogEmail4linkSendEmailFailedEvent $even
$this->logService->logEmail4LinkEmailFailed($event->getVisitor(), $event->getHref());
}

/**
* @param VirtualPageTrackerEvent $event
* @return void
* @throws IllegalObjectTypeException
* @throws UnknownObjectException
*/
public function logVirtualPageRequest(VirtualPageTrackerEvent $event): void
{
$this->logService->logVirtualPageRequest($event->getVisitor(), $event->getParameter());
}

/**
* @param DownloadEvent $event
* @return void
Expand Down
6 changes: 6 additions & 0 deletions Classes/Domain/Model/Log.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class Log extends AbstractModel
public const STATUS_PAGEVISIT3 = 41;
public const STATUS_PAGEVISIT4 = 42;
public const STATUS_PAGEVISIT5 = 43;
public const STATUS_VIRTUALPAGEVISIT = 48;
public const STATUS_DOWNLOAD = 50;
public const STATUS_SEARCH = 55;
public const STATUS_ACTION = 60;
Expand Down Expand Up @@ -166,6 +167,11 @@ public function getSearch(): ?Search
return $searchRepository->findByIdentifier($searchUid);
}

public function getVirtualPath(): string
{
return $this->getPropertyByKey('virtualPath');
}

public function getLinklistener(): ?Linklistener
{
$linklistenerUid = (int)$this->getPropertyByKey('linklistener');
Expand Down
12 changes: 12 additions & 0 deletions Classes/Domain/Service/LogService.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ public function logEmail4LinkEmailFailed(Visitor $visitor, string $href): void
$this->log(Log::STATUS_IDENTIFIED_EMAIL4LINK_SENDEMAILFAILED, $visitor, ['href' => $href]);
}

/**
* @param Visitor $visitor
* @param string $parameter
* @return void
* @throws IllegalObjectTypeException
* @throws UnknownObjectException
*/
public function logVirtualPageRequest(Visitor $visitor, string $parameter): void
{
$this->log(Log::STATUS_VIRTUALPAGEVISIT, $visitor, ['virtualPath' => $parameter]);
}

/**
* @param Download $download
* @return void
Expand Down
4 changes: 1 addition & 3 deletions Classes/Domain/Tracker/DownloadTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ public function addDownload(string $href, int $pageIdentifier): void
$download->setVisitor($this->visitor);
$this->visitorRepository->update($this->visitor);
$this->visitorRepository->persistAll();
$this->eventDispatcher->dispatch(
GeneralUtility::makeInstance(DownloadEvent::class, $this->visitor, $download)
);
$this->eventDispatcher->dispatch(new DownloadEvent($this->visitor, $download));
}
}

Expand Down
4 changes: 1 addition & 3 deletions Classes/Domain/Tracker/LinkClickTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ public function addLinkClick(int $linkclickIdentifier, int $pageUid): void
$this->linkclickRepository->add($linkclick);
$this->linkclickRepository->persistAll();

$this->eventDispatcher->dispatch(
GeneralUtility::makeInstance(LinkClickEvent::class, $this->visitor, $linklistener, $pageUid)
);
$this->eventDispatcher->dispatch(new LinkClickEvent($this->visitor, $linklistener, $pageUid));
}
}
}
4 changes: 1 addition & 3 deletions Classes/Domain/Tracker/NewsTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ public function track(Visitor $visitor, array $arguments, Pagevisit $pagevisit =
$visitor->addNewsvisit($newsvisit);
$this->visitorRepository->update($visitor);
$this->visitorRepository->persistAll();
$this->eventDispatcher->dispatch(
GeneralUtility::makeInstance(NewsTrackerEvent::class, $visitor, $newsvisit, $arguments)
);
$this->eventDispatcher->dispatch(new NewsTrackerEvent($visitor, $newsvisit, $arguments));
}
}

Expand Down
4 changes: 1 addition & 3 deletions Classes/Domain/Tracker/PageTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ public function track(Visitor $visitor, array $arguments): ?Pagevisit
$visitor->setVisits($visitor->getNumberOfUniquePagevisits());
$this->visitorRepository->update($visitor);
$this->visitorRepository->persistAll();
$this->eventDispatcher->dispatch(
GeneralUtility::makeInstance(PageTrackerEvent::class, $visitor, $pagevisit, $arguments)
);
$this->eventDispatcher->dispatch(new PageTrackerEvent($visitor, $pagevisit, $arguments));
return $pagevisit;
}
return null;
Expand Down
37 changes: 25 additions & 12 deletions Classes/Domain/Tracker/SearchTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,29 +43,27 @@ public function __construct(VisitorRepository $visitorRepository, EventDispatche
public function track(Visitor $visitor, array $arguments, Pagevisit $pagevisit = null): void
{
if ($this->isTrackingActivated($visitor, $arguments)) {
$searchTerm = $this->getSearchTerm($arguments['currentUrl']);
$queryBuilder = DatabaseUtility::getQueryBuilderForTable(Search::TABLE_NAME);
$properties = [
'searchterm' => $searchTerm,
'searchterm' => $this->getSearchTerm($arguments),
'visitor' => $visitor->getUid(),
'crdate' => time(),
'tstamp' => time(),
'sys_language_uid' => -1,
];
if ($pagevisit !== null) {
$properties['pagevisit'] = $pagevisit->getUid();
}
$queryBuilder->insert(Search::TABLE_NAME)->values($properties)->executeStatement();
$searchUid = $queryBuilder->getConnection()->lastInsertId();
$this->eventDispatcher->dispatch(
GeneralUtility::makeInstance(SearchEvent::class, $visitor, (int)$searchUid)
);
$this->eventDispatcher->dispatch(new SearchEvent($visitor, (int)$searchUid));
}
}

protected function isTrackingActivated(Visitor $visitor, array $arguments): bool
{
return $visitor->isNotBlacklisted() && $this->isTrackingActivatedInSettings()
&& $this->isSearchTermGiven($arguments['currentUrl']);
&& $this->isAnySearchTermGiven($arguments);
}

/**
Expand All @@ -75,22 +73,37 @@ protected function isTrackingActivated(Visitor $visitor, array $arguments): bool
*/
protected function isTrackingActivatedInSettings(): bool
{
return !empty($this->settings['tracking']['search']['_enable'])
&& $this->settings['tracking']['search']['_enable'] === '1';
return ($this->settings['tracking']['search']['_enable'] ?? false) === '1';
}

protected function isAnySearchTermGiven(array $arguments): bool
{
return $this->getSearchTerm($arguments) !== '';
}

protected function getSearchTerm(array $arguments): string
{
if (isset($arguments['parameter'])) {
return $arguments['parameter'];
}
if ($this->isSearchTermGivenInUrl($arguments['currentUrl'])) {
return $this->getSearchTermFromUrl($arguments['currentUrl']);
}
return '';
}

protected function isSearchTermGiven(string $currentUrl): bool
protected function isSearchTermGivenInUrl(string $currentUrl): bool
{
return $this->getSearchTerm($currentUrl) !== '';
return $this->getSearchTermFromUrl($currentUrl) !== '';
}

/**
* Read the searchterm from URL GET parameters
* Read searchterm from URL GET parameters
*
* @param string $currentUrl
* @return string
*/
protected function getSearchTerm(string $currentUrl): string
protected function getSearchTermFromUrl(string $currentUrl): string
{
$parsed = parse_url($currentUrl);
if (!empty($parsed['query']) && !empty($this->settings['tracking']['search']['getParameters'])) {
Expand Down
4 changes: 2 additions & 2 deletions Classes/Domain/Tracker/UtmTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function trackPage(PageTrackerEvent $event): void
try {
$this->utmRepository->add($utm);
$this->utmRepository->persistAll();
$this->eventDispatcher->dispatch(GeneralUtility::makeInstance(UtmEvent::class, $utm));
$this->eventDispatcher->dispatch(new UtmEvent($utm));
} catch (Throwable $exception) {
// Do nothing
}
Expand All @@ -56,7 +56,7 @@ public function trackNews(NewsTrackerEvent $event): void
try {
$this->utmRepository->add($utm);
$this->utmRepository->persistAll();
$this->eventDispatcher->dispatch(GeneralUtility::makeInstance(UtmEvent::class, $utm));
$this->eventDispatcher->dispatch(new UtmEvent($utm));
} catch (Throwable $exception) {
// Do nothing
}
Expand Down
Loading

0 comments on commit 5361d91

Please sign in to comment.