on
07-Jun-2016
14:27
- edited on
05-Jun-2023
22:52
by
JimmyPackets
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:
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 -->
You need to install the irule on your Virtual Server.
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
Github : https://github.com/e-XpertSolutions/f5
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 -->
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.5We 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!
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
}
}
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]]