Некоторые веб-приложения не имеют единого шаблона вывода, куда можно было бы просто вставить код счетчика (Google Analytics или Яндекс Метрика). В таких приложениях HTML-страницы генерируются различными способами и по различным шаблонам. Чтобы вставить в такие системы код счетчика, можно использовать возможности Apache HTTPD.
Логика работы такова:
1) Перехватывается сгенерированный HTML-трафик
2) В перехваченном тексте ищется место, в которое необходимо вставить счетчик. В общем случае, это «</body>», так как счетчики обычно вставляются перед этим тэгом (можно искать «</header>»)
3) Найденные вхождения заменяются на код со счетчиком
4) Трафик отдается клиенту
Перехватить трафик средствами apache можно, используя его в качестве прокси. Заменять текст можно утилитой sed (она есть также и для windows). Помимо этого, надо удостовериться, что замена идет в простом тексте, а не сжатом, так как сервер может сжимать трафик внутренними средствами. До замены нужно распаковать трафик. Далее, произведя замену, нужно снова сжать его.
Можно использовать следующие настройки apache:
Listen *:80 Listen 127.0.0.1:20001 <VirtualHost 127.0.0.1:20001> # интеграция с приложением ProxyPreserveHost On ProxyPass / ajp://127.0.0.1:8009/ min=5 ttl=120 keepalive=On ping=1 ProxyPassReverse / ajp://127.0.0.1:8009/ # фильтр для замены текста ExtFilterDefine metrika mode=output \ cmd="C:/apache_scripts/metrika_filter.cmd" \ intype=text/html # распаковка трафика и применение замены AddOutputFilterByType INFLATE;metrika text/html </VirtualHost> <VirtualHost *:80> # прокси для сжатия получившегося трафика ProxyPreserveHost On ProxyPass / http://127.0.0.1:20001/ min=5 ttl=120 keepalive=On ping=1 ProxyPassReverse / http://127.0.0.1:20001/ # сжатие html-трафика AddOutputFilterByType DEFLATE text/html </VirtualHost>
Таким образом, создаются два виртуальных хоста, один ловит поток другого. Теоретически, можно было бы применить фильтры в нужном порядке, однако практически это сделать не удается. По умолчанию вначале выполняется распаковка, потом сжатие, потом замена. Естественно, нужен другой порядок. Применение модуля mod_filter с его механизмом filter chaining здесь не помогает, так как он не взаимодействует с фильтрами, установленными с помощью ExtFilterDefine (возможно, это связано с багами в реализации модулей для apache 2.2).
Код файла metrika_filter.cmd:
@echo off set _command="s/<\/body>/<!-- Yandex.Metrika counter --><script type='text\/javascript'>(function (d, w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounterXXXXXX = new Ya.Metrika({id:XXXXXX, enableAll: true, ut:'noindex'}); } catch(e) {} }); var n = d.getElementsByTagName('script')[0], s = d.createElement('script'), f = function () { n.parentNode.insertBefore(s, n); }; s.type = 'text\/javascript'; s.async = true; s.src = (d.location.protocol == 'https:' ? 'https:' : 'http:') + '\/\/mc.yandex.ru\/metrika\/watch.js'; if (w.opera == '[object Opera]') { d.addEventListener('DOMContentLoaded', f); } else { f(); } })(document, window, 'yandex_metrika_callbacks');<\/script><noscript><div><img src='\/\/mc.yandex.ru\/watch\/XXXXXX?ut=noindex' style='position:absolute; left:-9999px;' alt='' \/><\/div><\/noscript><!-- \/Yandex.Metrika counter --><\/body>/gi" sed %_command%
В любом случае, предлагаемое решение не годится для постоянного использование и может быть применено только в ограниченном периоде для выявления загруженности сервера и получения статистики.