Google Analytics script injection
Problem this snippet solves:
Add google analytics script in the html content of the HTTP response. Works also for other Analytics providers like Piwik.
How to use this snippet:
Installation
Files
The code below has to be imported as an ifile.
By default, you must name this ifile google.js but you can change it in the irule if required.
Google Analytics code :
<!-- Google Analytics --> <script> window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date; ga('create', '$static::tracking_id', 'auto'); ga('send', 'pageview'); </script> <script async src='https://www.google-analytics.com/analytics.js'></script> <!-- End Google Analytics -->
Piwik javascript code :
<!-- Piwik --> <script type="text/javascript"> var _paq = _paq || []; _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); (function() { var u="//$static::piwik_url/"; _paq.push(['setTrackerUrl', u+'piwik.php']); _paq.push(['setSiteId', {$static::siteid}]); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s); })(); </script> <!-- End Piwik Code -->
irule
You need to install the irule on your Virtual Server.
Variables
set static::tracking_id "UA-XXXXX-Y" # replace the Google Tracking ID by your own set static::siteid "UA-XXXXX-Y" # replace the Piwik Site ID by your own set static::piwik_url "https://www.mypiwik.com/piwik/piwik" # replace the Piwik URL by your own
Features
Version 1.0
- Insert Google Analytics JS code within html response
- support for Piwik JS insertion
- Manage Multiple TrackingID by hostname (see Multiple "hostname and TrackingID section")
Backlog
- Add logging
External links
Github : https://github.com/e-XpertSolutions/f5
BONUS : Multiple hostname and TrackingID
Prerequisite
You need to add a string based Datagroup named HOST_TRACKING_MAPPING.
ltm data-group internal HOST_TRACKING_MAPPING { records { blog.e-xpertsolutions.com { data UA-XXXXX-Z } www.e-xpertsolutions.com { data UA-XXXXX-Y } } type string }
The google.js ifile need to be replaced by the following example :
<!-- Google Analytics --> <script> window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date; ga('create', '$tracking_id', 'auto'); ga('send', 'pageview'); </script> <script async src='https://www.google-analytics.com/analytics.js'></script> <!-- End Google Analytics -->
Irule
when RULE_INIT { set static::default_trackingid "UA-XXXXX-Y" } when HTTP_REQUEST { HTTP::header remove "Accept-Encoding" set host [HTTP::host] } when HTTP_RESPONSE { if { [HTTP::header Content-Type] contains "text/html" } { if { [HTTP::header exists "Content-Length"] } { set content_length [HTTP::header "Content-Length"] } else { set content_length 1000000 } if { $content_length > 0 } { HTTP::collect $content_length } } } when HTTP_RESPONSE_DATA { set search "</head>" set tracking_id [class match -value -- $host equals HOST_TRACKING_MAPPING] if { $tracking_id eq "" } { set tracking_id $static::default_trackingid } HTTP::payload replace 0 $content_length [string map [list $search "[subst -nocommands -nobackslashes [ifile get google.js]]</head>"] [HTTP::payload]] HTTP::release }
Code :
when RULE_INIT { set static::tracking_id "UA-XXXXX-Y" set static::siteid "XXXXX" set static::piwik_url "https://www.piwik.url/piwik/piwik" } when HTTP_REQUEST { HTTP::header remove "Accept-Encoding" } when HTTP_RESPONSE { if { [HTTP::header Content-Type] contains "text/html" } { if { [HTTP::header exists "Content-Length"] } { set content_length [HTTP::header "Content-Length"] } else { set content_length 1000000 } if { $content_length > 0 } { HTTP::collect $content_length } } } when HTTP_RESPONSE_DATA { set search "" HTTP::payload replace 0 $content_length [string map [list $search "[subst -nocommands -nobackslashes [ifile get google.js]]"] [HTTP::payload]] HTTP::release }
Tested this on version:
11.5- bitisuvanje_349Nimbostratus
We did everything as described trying to get some data to Google Analytics, single hostname, following the instructions. No traffic reaches Google Analytics. Do you guys have possible update on this topic?
We use BIG-IP LTM.
Thanks!
- Danny_TixNimbostratus
We arrived at a solution using HTML profiles - am I overlooking any major downsides to this approach?
HTML profile (abbreviated):
ltm profile html /Common/html-ga { app-service none content-detection disabled content-selection { application/xhtml+xml text/xhtml text/html } defaults-from /Common/html description none rules { /Common/GT-Private /Common/GA-Private } } ltm html-rule tag-append-html /Common/GT-Private { action { text "" } description "Google Tag Manager" match { tag-name body } } ltm html-rule tag-prepend-html /Common/GA-Private { action { text "" } description "Google Analytics" match { tag-name /head } }
Sample iRule (optional and abbreviated):
when HTTP_REQUEST { set disable_html 0 switch -glob [string tolower [HTTP::uri]] { /secure_app* { special case for app that leaks data in URLs pool secure_app set disable_html 1 } /legacy_app/pagenotfound/* { ... special case for app that redirects 404s ... pool legacy_app set disable_html 1 } default { ... normal logic ... pool main_app } } } when HTTP_RESPONSE { if { [HTTP::status] == 404 || [HTTP::status] == 403 || $disable_html == 1 }{ HTML::disable } }
- Bryan_McCoyNimbostratus
I was able to get this to work for a different .js file insertion but had to make a change to the string map line at the end to remove a set of quotes and include the partition.
HTTP::payload replace 0 $content_length [string map [list $search [subst -nocommands -nobackslashes [ifile get "/Common/newrelic.js"]]</head>] [HTTP::payload]]