I've been looking into using Google Tag Manager on my website, but I've failed at the first hurdle due to the default Google include code being blocked by the mod-security installation on my server:
Standard GTM include code:
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-XXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');</script>
<!-- End Google Tag Manager -->
Response from mod-security:
WARNING: Possibly malicious iframe tag in output
Message: Outbound Anomaly Score Exceeded (score 15): Possibly malicious iframe tag in output
The rules triggered are ids 981000 and 981001.
I can understand why mod-security might think an iframe with "display:none;visibility:hidden" could be possibly malicious, and removing the style attribute stops rule 981001 from triggering, but the request still fails because of rule 981000.
981000 seems to have a strong opinion about what the width and height attributes should be, but I've tried setting them to '1' and '10' to no avail :-(
Does anyone know how to format an iframe to fit this rule? or how to change the GTM include code so that it doesn't contain the iframe?
Thanks
PS: I know you can solve this problem by removing the whole noscript area, but I'm looking for a solution that doesn't alter the functionality of the include code.
PPS: this is the pattern that rule 981000 is matching, I can understand about half of it before my brain explodes in a cloud of nested capture groups ;-)
Pattern match "<\W*iframe[^>]+?\b(?:width|height)\b\W*?=\W*?["']?[^"'1-9]*?(?:(?:20|1?\d(?:\.\d*)?)(?![\d%.])|[0-3](?:\.\d*)?%)"
After a lot of experimentation - I found the following code works:
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-XXXXXX"
height="21" width="21" class ="noDisplay"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');</script>
<!-- End Google Tag Manager -->
It seems rule 981000 will fire for any iframe that is less than 21 pixels or 3% in width or height. Moving the visibility and display style information to an external stylesheet prevented rule 981001 from firing.
.noDisplay {
display:none;
visibility:hidden;
}
The code now passes mod security and includes GTM in the page in (pretty much) the way Google intended.
I hope that helps someone else struggling with the same problem :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With