diff --git a/README.md b/README.md index 464cec39..3955df34 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ The project uses several custom `$settings` in `settings.php`: | `telegram_secret_token` | Secret token for Telegram webhook verification | | `telegram_chat_id` | Telegram chat ID for moderation notifications | | `app_foresight` | (default: `TRUE`) Allows to disable the ForesightJS prefetch library for an environment. Only active for anonymous users. When disabled, no link prefetching is performed. | +| `app_yandex_metrika_id` | Yandex.Metrika counter ID. When set, adds a tracking pixel (``) to the bottom of every page. | ## 🧬 Quality Tools diff --git a/app/modules/main/src/Hook/Core/YandexMetrikaPageBottom.php b/app/modules/main/src/Hook/Core/YandexMetrikaPageBottom.php new file mode 100644 index 00000000..28766599 --- /dev/null +++ b/app/modules/main/src/Hook/Core/YandexMetrikaPageBottom.php @@ -0,0 +1,30 @@ + 'html_tag', + '#tag' => 'img', + '#attributes' => [ + 'src' => 'https://mc.yandex.ru/watch/' . \rawurlencode($metrika_id), + 'style' => 'position:absolute; left:-9999px;', + 'alt' => '', + ], + ]; + } + +} diff --git a/app/modules/main/tests/src/Unit/Hook/Core/YandexMetrikaPageBottomTest.php b/app/modules/main/tests/src/Unit/Hook/Core/YandexMetrikaPageBottomTest.php new file mode 100644 index 00000000..ae821209 --- /dev/null +++ b/app/modules/main/tests/src/Unit/Hook/Core/YandexMetrikaPageBottomTest.php @@ -0,0 +1,74 @@ + '']); + $hook = new YandexMetrikaPageBottom(); + $page_bottom = []; + + $hook($page_bottom); + + self::assertEmpty($page_bottom); + } + + public function testNonStringAddsNothing(): void { + new Settings(['app_yandex_metrika_id' => 123]); + $hook = new YandexMetrikaPageBottom(); + $page_bottom = []; + + $hook($page_bottom); + + self::assertEmpty($page_bottom); + } + + public function testValidIdAddsImage(): void { + new Settings(['app_yandex_metrika_id' => '48390929']); + $hook = new YandexMetrikaPageBottom(); + $page_bottom = []; + + $hook($page_bottom); + + self::assertArrayHasKey('app_main_yandex_metrika', $page_bottom); + self::assertSame('html_tag', $page_bottom['app_main_yandex_metrika']['#type']); + self::assertSame('img', $page_bottom['app_main_yandex_metrika']['#tag']); + self::assertSame('https://mc.yandex.ru/watch/48390929', $page_bottom['app_main_yandex_metrika']['#attributes']['src']); + self::assertSame('position:absolute; left:-9999px;', $page_bottom['app_main_yandex_metrika']['#attributes']['style']); + self::assertSame('', $page_bottom['app_main_yandex_metrika']['#attributes']['alt']); + } + + public function testIdIsEncoded(): void { + new Settings(['app_yandex_metrika_id' => '48<39>09']); + $hook = new YandexMetrikaPageBottom(); + $page_bottom = []; + + $hook($page_bottom); + + self::assertSame('https://mc.yandex.ru/watch/48%3C39%3E09', $page_bottom['app_main_yandex_metrika']['#attributes']['src']); + } + +} diff --git a/assets/scaffold/local.settings.php b/assets/scaffold/local.settings.php index e8c24f22..cd8bf756 100644 --- a/assets/scaffold/local.settings.php +++ b/assets/scaffold/local.settings.php @@ -55,5 +55,6 @@ $settings['telegram_chat_id'] = NULL; $settings['telegram_secret_token'] = NULL; $settings['app_foresight'] = FALSE; +$settings['app_yandex_metrika_id'] = NULL; $config['cache_pilot.settings']['connection_dsn'] = 'tcp://php:9000'; diff --git a/config/cspell/dictionary.txt b/config/cspell/dictionary.txt index a9f021df..d259f14c 100644 --- a/config/cspell/dictionary.txt +++ b/config/cspell/dictionary.txt @@ -37,3 +37,5 @@ TYPEHINT Webmozart wght youtu +metrika +Metrika