Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic inclusion of piwik code by means of server side filtering inside apache server

After a few hours of fruitless attempts I would like to ask you all for a little assistance with a simple setup:

For a bunch of web applications and sites I run using the apache2 http server I use Piwik for a simple statistical overview. That works fine. What annoys me is that with every additional app/page and every update/upgrade I have to take care to manually maintain the javascript code required by piwik to be included into the html markup.

To simplify that maintainance I want have that code added by apache: I want to use some apache modules: mod_filter, mod_env, mod_substitute and mod_include. The idea is to have all html files delivered injected with the piwik code by means of a filter. That filter uses substitution to prepend the </body> tag with a placeholder. That placeholder again is a sgml tag processed by server side inclusion. That inclusion finally replaces the placeholder with the piwik code which is given the required numerical site id in a dynamic way.

So all that is left when configuring a new virtual host will be to specify two lines inside the apache configuration:

  1. include the filter setup stored in a small file
  2. specify the numerical piwik site id by setting an environment variable

No more fiddling around with template files inside the apps!


I am very close to a solution, one step is missing...

Maybe some of you gurus here spot what I am missing !


The (much simplyfied) configuration of the virtual host:

<VirtualHost *:80>
ServerAdmin [email protected]
ServerName some.domain.here

# include local piwik setup
SetEnv PIWIK_ID 5
Include /etc/apache2/vhosts.d/_internal.inc

DocumentRoot /some/path/here
<Directory  "/some/path/here">
    Options None
    AllowOverride none
    Order allow,deny  
    Allow from all    
</Directory>

</VirtualHost>

The (shortened) configuration file included above:

# some internal resources 
<Directory "/srv/www/internal">
    Options None
    AllowOverride None
    Order deny,allow
    Allow from all 
</Directory>

# ----------
# internal requests to include the piwik tracking code at the bottom of every html page

# prepare required filters 
FilterDeclare  filter_PIWIK 
FilterProvider filter_PIWIK SUBSTITUTE resp=Content-Type $text/html 
FilterProvider filter_PIWIK INCLUDES   resp=Content-Type $text/html 
FilterChain    filter_PIWIK SUBSTITUTE 's|</body>|<!--#include virtual="/piwik" --></body>|ni'

# map virtual request to the file system 
Alias /piwik /srv/www/internal/piwik.php

Last file /srv/www/internal/piwik.php referenced in the Alias above: This is the file providing the piwik code. It is like those computed by piwik itself, except for one thing: The numerical site index is dynamically replaced with a value from the environment variable

<?php 
define('piwikBase','domain.here/stats/');
define('piwikSite',apache_getenv('PIWIK_ID'));
if(is_numeric(piwikSite)){ 
?>
<!-- Piwik: begin tracking code -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://<?php echo piwikBase; ?>" : "http://<?php echo piwikBase; ?>");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", <?php echo piwikSite; ?>);
piwikTracker.trackPageView();
piwikTracker.enableLinkTracking();
} catch( err ) {}
</script><noscript><p><img src="http://<?php echo piwikBase; ?>piwik.php?idsite=<?php echo piwikSite; ?>" style="border:0" alt="" /></p></noscript>
<!-- Piwik: end tracking code -->
<?php } else { ?>
<!-- invalid piwik site id: <?php echo piwikSite;?> -->
<?php } ?>

What I got working so far:

  • The php based dynamic piwik scniplet is working, I can call it with a browser and see the code in the html markup source complete with a numerical id taken from an environment variable defined in the configuration for testing purposes. Also, when I specify a nin-numerical id that way I get the expected placeholder <!-- invalid piwik site id: ... -->
  • The filter works (is applied) in general: the </body> tag is replaced by the placeholder . I can check this by commenting out the FilterProvider adding the INCLUDES directive at the beginning. In that case I see the placeholder in the generated html markup.
  • That FilterProvider is actually recognized and executed by apache: before I had errors about a missing Options +Includes in the configuratioon and the like, that is sorted out, apache does not complain any more. Also the placeholder is removed again, when the FilterProvider mentioned above is not commented out. So I assume the include process is working.
  • Aparently the problem is not that the server side inclusion refers a php script. I get no error messages and tests with a static file instead showed no difference.

It appears as if the setup works fine, no errors thrown, nothing strange in the rewrite log. However although the include filter aparently works the content I would expect to be included is empty. The placeholder inserted by the first SUBSTITUTE step is replaced again by the second INCLUDE step. but unfortunately by empty content, so it is removed. I have no idea why.

like image 215
arkascha Avatar asked Nov 13 '22 16:11

arkascha


1 Answers

Ok, I found the answer myself. This was the sixth attempt to dig through that and finally I succeeded. All I had to do was change the definition and usage of the filter codes. Everything else was just fine:

FilterDeclare PIWIK_token
FilterProvider PIWIK_token SUBSTITUTE resp=Content-Type $text/html
SUBSTITUTE 's|</body>|<!--#include virtual="/piwik" --></body>|ni'
FilterDeclare PIWIK_code
FilterProvider PIWIK_code INCLUDES resp=Content-Type $text/html
FilterChain PIWIK_token PIWIK_code

I am surprised no one else tries stuff like this. Now I can remove all those script snippets inserted and so many places by hand without having to think of them again when doing an upgrade or when I add pages or whole sites. All I need is to specify the sites piwik id using those two lines mentioned. Great.

Update on 2013-01-23:

I have been using this solution for a few weeks now and did not enounter a single problem with the setup. So I made a short description. Mabe this this helps someone:

> Piwik tracking & automatic snippet inclusion

like image 117
arkascha Avatar answered Nov 15 '22 07:11

arkascha