feat: tracking integration with GTM and CMP

This commit is contained in:
Björn Fromme
2026-01-27 17:31:41 +01:00
parent d5944bf717
commit e9548d9f38
21 changed files with 453 additions and 51 deletions
+54 -17
View File
@@ -5,8 +5,11 @@ declare(strict_types=1);
namespace App\Tests\EventListener;
use App\EventListener\DomainThemeListener;
use App\Model\DomainConfig;
use App\Service\DomainConfigProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
@@ -21,9 +24,9 @@ class DomainThemeListenerTest extends TestCase
public function testSetsThemeAttributeForMatchingDomain(): void
{
$listener = new DomainThemeListener([
'sbw-reisen' => 'sbw',
'ser-reisen' => 'ser',
$listener = $this->createListener([
'sbw-reisen.de' => ['theme' => 'sbw'],
'ser-reisen.de' => ['theme' => 'ser'],
]);
$request = Request::create('https://www.sbw-reisen.de/bookings/create');
@@ -34,10 +37,32 @@ class DomainThemeListenerTest extends TestCase
$this->assertSame('sbw', $request->attributes->get(DomainThemeListener::THEME_ATTRIBUTE));
}
public function testSetsDomainConfigAttribute(): void
{
$listener = $this->createListener([
'sbw-reisen.de' => [
'theme' => 'sbw',
'gtm_id' => 'GTM-123',
'cmp_url' => 'https://cmp.example.com',
],
]);
$request = Request::create('https://www.sbw-reisen.de/bookings/create');
$event = new RequestEvent($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST);
$listener($event);
$config = $request->attributes->get(DomainThemeListener::DOMAIN_CONFIG_ATTRIBUTE);
$this->assertInstanceOf(DomainConfig::class, $config);
$this->assertSame('sbw', $config->theme);
$this->assertSame('GTM-123', $config->gtmId);
$this->assertSame('https://cmp.example.com', $config->cmpUrl);
}
public function testSetsDefaultThemeForUnknownDomain(): void
{
$listener = new DomainThemeListener([
'sbw-reisen' => 'sbw',
$listener = $this->createListener([
'sbw-reisen.de' => ['theme' => 'sbw'],
]);
$request = Request::create('https://www.ep-reisen.de/bookings/create');
@@ -50,8 +75,8 @@ class DomainThemeListenerTest extends TestCase
public function testMatchesPartialDomain(): void
{
$listener = new DomainThemeListener([
'ser-reisen' => 'ser',
$listener = $this->createListener([
'ser-reisen.de' => ['theme' => 'ser'],
]);
$request = Request::create('https://portal.ser-reisen.de/bookings');
@@ -64,8 +89,8 @@ class DomainThemeListenerTest extends TestCase
public function testIgnoresSubRequests(): void
{
$listener = new DomainThemeListener([
'sbw-reisen' => 'sbw',
$listener = $this->createListener([
'sbw-reisen.de' => ['theme' => 'sbw'],
]);
$request = Request::create('https://www.sbw-reisen.de/bookings/create');
@@ -78,22 +103,23 @@ class DomainThemeListenerTest extends TestCase
public function testFirstMatchWins(): void
{
$listener = new DomainThemeListener([
'reisen' => 'generic',
'sbw-reisen' => 'sbw',
// When a host matches multiple patterns, the first pattern in iteration order wins
$listener = $this->createListener([
'portal.example.com' => ['theme' => 'portal'],
'example.com' => ['theme' => 'main'],
]);
$request = Request::create('https://www.sbw-reisen.de/bookings/create');
$request = Request::create('https://deep.portal.example.com/bookings/create');
$event = new RequestEvent($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST);
$listener($event);
$this->assertSame('generic', $request->attributes->get(DomainThemeListener::THEME_ATTRIBUTE));
$this->assertSame('portal', $request->attributes->get(DomainThemeListener::THEME_ATTRIBUTE));
}
public function testEmptyMapReturnsDefaultTheme(): void
{
$listener = new DomainThemeListener([]);
$listener = $this->createListener([]);
$request = Request::create('https://www.sbw-reisen.de/bookings/create');
$event = new RequestEvent($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST);
@@ -105,8 +131,8 @@ class DomainThemeListenerTest extends TestCase
public function testMatchesLocalhostForDevelopment(): void
{
$listener = new DomainThemeListener([
'localhost' => 'sbw',
$listener = $this->createListener([
'localhost' => ['theme' => 'sbw'],
]);
$request = Request::create('http://localhost/bookings/create');
@@ -116,4 +142,15 @@ class DomainThemeListenerTest extends TestCase
$this->assertSame('sbw', $request->attributes->get(DomainThemeListener::THEME_ATTRIBUTE));
}
/**
* @param array<string, array{theme?: string, gtm_id?: string, cmp_url?: string}> $domainConfig
*/
private function createListener(array $domainConfig): DomainThemeListener
{
$requestStack = new RequestStack();
$provider = new DomainConfigProvider($domainConfig, $requestStack);
return new DomainThemeListener($provider);
}
}
+145
View File
@@ -0,0 +1,145 @@
<?php
declare(strict_types=1);
namespace App\Tests\Service;
use App\Model\DomainConfig;
use App\Service\DomainConfigProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
class DomainConfigProviderTest extends TestCase
{
public function testReturnsConfigForExactMatch(): void
{
$provider = $this->createProvider([
'example.com' => [
'theme' => 'custom',
'gtm_id' => 'GTM-123',
'cmp_url' => 'https://cmp.example.com',
],
], 'example.com');
$config = $provider->getConfig();
$this->assertSame('custom', $config->theme);
$this->assertSame('GTM-123', $config->gtmId);
$this->assertSame('https://cmp.example.com', $config->cmpUrl);
}
public function testReturnsConfigForSubdomainMatch(): void
{
$provider = $this->createProvider([
'example.com' => [
'theme' => 'custom',
'gtm_id' => 'GTM-456',
'cmp_url' => 'https://cmp.example.com',
],
], 'www.example.com');
$config = $provider->getConfig();
$this->assertSame('custom', $config->theme);
$this->assertSame('GTM-456', $config->gtmId);
}
public function testReturnsDefaultConfigForUnknownDomain(): void
{
$provider = $this->createProvider([
'example.com' => [
'theme' => 'custom',
'gtm_id' => 'GTM-123',
'cmp_url' => 'https://cmp.example.com',
],
], 'unknown.com');
$config = $provider->getConfig();
$this->assertSame(DomainConfig::DEFAULT_THEME, $config->theme);
$this->assertSame('', $config->gtmId);
$this->assertSame('', $config->cmpUrl);
}
public function testReturnsDefaultConfigWhenNoRequest(): void
{
$requestStack = new RequestStack();
$provider = new DomainConfigProvider([], $requestStack);
$config = $provider->getConfig();
$this->assertSame(DomainConfig::DEFAULT_THEME, $config->theme);
}
public function testHandlesMissingConfigValues(): void
{
$provider = $this->createProvider([
'example.com' => [
'theme' => 'custom',
],
], 'example.com');
$config = $provider->getConfig();
$this->assertSame('custom', $config->theme);
$this->assertSame('', $config->gtmId);
$this->assertSame('', $config->cmpUrl);
}
public function testCachesConfigForSameHost(): void
{
$provider = $this->createProvider([
'example.com' => [
'theme' => 'custom',
'gtm_id' => 'GTM-123',
'cmp_url' => 'https://cmp.example.com',
],
], 'example.com');
$config1 = $provider->getConfigForHost('example.com');
$config2 = $provider->getConfigForHost('example.com');
$this->assertSame($config1, $config2);
}
public function testFirstMatchWins(): void
{
// When a host matches multiple patterns, the first pattern in iteration order wins
// Here 'deep.portal.example.com' matches both 'portal.example.com' (via subdomain)
// and 'example.com' (via subdomain), but portal.example.com is checked first
$provider = $this->createProvider([
'portal.example.com' => ['theme' => 'portal'],
'example.com' => ['theme' => 'main'],
], 'deep.portal.example.com');
$config = $provider->getConfig();
$this->assertSame('portal', $config->theme);
}
public function testCaseInsensitiveMatching(): void
{
$provider = $this->createProvider([
'Example.COM' => [
'theme' => 'custom',
],
], 'EXAMPLE.com');
$config = $provider->getConfig();
$this->assertSame('custom', $config->theme);
}
/**
* @param array<string, array{theme?: string, gtm_id?: string, cmp_url?: string}> $domainConfig
*/
private function createProvider(array $domainConfig, string $host): DomainConfigProvider
{
$request = Request::create('https://'.$host.'/');
$requestStack = new RequestStack();
$requestStack->push($request);
return new DomainConfigProvider($domainConfig, $requestStack);
}
}