I had a problem: Kathy and Denise wanted Google Analytics configured for our demo Genie site that can be found at http://genie.andornot.com. However, Genie doesn't provide an easy way to centrally add the couple lines of Google Analytics code to every page served up by the application. For that matter, neither does any WebPublisher PRO site right out-of-the-box (easy-peasy though if we're using ASK and our WebPubResults control).
So what do we do? Instead of updating 10s if not 100s or 1000s of files manually one-by-one (crossing my fingers that I could find them all) and hoping my code wouldn't need to change anytime soon, I came up with a modified version of the Web Analytics Tracking Module available on Microsoft's IIS.net site. Now, with a little elbow grease for initial server setup (seriously, not very much elbow grease at all), turning on site tracking for any site on our servers is simply a matter of placing a DLL in our application's bin directory, and adding a couple lines to our site's Web.config. Sweet.
Why not just use the original IIS.net Web Analytics Module?
Before jumping in and explaining how to set everything up, I should explain that I needed create my own custom build of the module because the module on IIS.net only works under IIS 7's integrated pipeline, not under IIS 7's classic pipeline (which Genie needs to run under) or IIS 6. The required changes ended up being relatively minor:
- Modified the ReadModuleConfiguration method in WebAnalyticsHttpModule.cs to the following:
/// Reads the module specific configuration properties
/// <param name="context"></param>
/// <returns>Boolean indicating the success/failure</returns>
private bool ReadModuleConfiguration(HttpContext context)
ConfigurationSection section = null;
section = WebConfigurationManager.GetSection(context, "system.webServer/webAnalytics", typeof(WebAnalyticsSection));
section = WebConfigurationManager.GetSection(context, "system.web/webAnalytics", typeof(WebAnalyticsSection));
if (section != null)
_webAnalyticsModuleConfig = (WebAnalyticsSection)section;
return _webAnalyticsModuleConfig != null;
- Add the classic pipeline <system.web>/<webAnalytics> schema to WebAnalytics_schema.xml:
<attribute name="trackingEnabled" type="bool" defautlValue="false"></attribute>
<attribute name="trackingScript" type="string" defautlValue="This is a default text"></attribute>
<attribute name="insertionPoint" type="enum" defaultValue="body">
<enum name="head" value="0" />
<enum name="body" value="1" />
- To make sure there's no versioning conflicts, I updated the Assembly's version to v1.1 in AssemblyInfo.cs (note the v1.1 references in the instructions below as opposed to v1.0):
Configure your server (one time only)
- Register the WebAnalyticsModule.dll in the GAC (for shiny stuff in the IIS 7 Manager GUI).
gacutil -if WebAnalyticsModule.dll
- Copy the WebAnalytics_schema.xml to "%windir%\system32\inetsrv\config\schema" folder.
- Add the following section definition to the "%windir%\system32\inetsrv\config\applicationhost.config" file in the sectionGroup for "system.webServer"
<section name="webAnalytics" overrideModeDefault="Allow" />
- Add the module to the IIS Manager configuration by adding to two collections in the "%windir%\system32\inetsrv\config\administration.config" file:
- Add the following to the moduleProviders collection:
Add the following to the modules collection:
<add name="WebAnalytics" type="WebAnalyticsModule.WebAnalyticsProvider, WebAnalyticsModule, Version=18.104.22.168, Culture=neutral, PublicKeyToken=c6b7132bcfe43312" />
<add name="WebAnalytics" />
Web Analytics Tracking now directly available in IIS 7 Manager (at least for sites running under Integrated Pipeline).
Configure your site/s
For each site you wish to have Google Analytics enabled on (or any other script/text/html you wish to have run on every page in the site), enable it according to the following instructions (slightly different for different flavours of IIS/pipeline).
IIS 7 Integrated Pipeline
- Place the same WebAnalyticsModule.dll in your application's bin directory or reference the GAC version via the Web.config's <system.web>/<compilation>/<assemblies> element.
- Add the module to the <modules> element in your Web.config. This can be done through the IIS Manager, but it's easier to simply add it directly in the Web.config:
<add name="WebAnalytics" type="WebAnalyticsModule.WebAnalyticsHttpModule, WebAnalyticsModule, Version=22.214.171.124, Culture=neutral, PublicKeyToken=c6b7132bcfe43312" />
- Specify the script/text you wish to have inserted and the location to insert it at. Again, this can be added directly in the Web.config. However, because the actual script/text needs to be encoded in order to keep your config file from going boink, it's a lot easier to just use the GUI.
Easy configuration within the IIS 7 Manager GUI, including properly encoding the script for the Web.config (safe for XML).
Enabling the above adds a <webAnalytics> element to the <system.webServer> section, looking something like (note the encoding):
var _gaq = _gaq || ;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script'); s.parentNode.insertBefore(ga, s);
</script>" insertionPoint="head" />
IIS 7 Classic Pipeline
Exactly the same as the IIS 7 integrated pipeline instructions above, with the following changes:
- Add the module reference to the classic pipeline specific <system.web>/<httpModules> section instead of the <system.webServer>/<modules> section.
- Make it easy for yourself, and add the script-specific settings (as in step 3 above) via the GUI in order to make sure it's all encoded properly, but then move/copy the resulting <webAnalytics> element from <system.webServer> (IIS 7 integrated pipeline specific) to <system.web>.
- Add the following to the <configuration>/<configSections> element in your Web.config (there should be a better way to add another sub-section to the already defined <system.web> declaration in the <configSections> element, so let me know in the comments if you know what it is):
<sectionGroup name="system.web" type="System.Web.Configuration.SystemWebSectionGroup, System.Web, Version=126.96.36.199, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<section name="webAnalytics" type="WebAnalyticsModule.WebAnalyticsSection, WebAnalyticsModule" />
Caveat: as your app is running under classic pipeline, not all text/html resources are running through ASP.NET, and therefore, if you have for i.e. .html and/or .asp pages you want the script automatically added to, you will need to map those extensions to also route through the ASP.NET runtime. Pretty standard classic pipeline stuff: without doing so, only pages with the .aspx extension will have the script added.
IIS 6 (Classic Pipeline)
I haven't tested it, but I see no reason why it won't work with the same set up as IIS 7 Classic Pipeline, with the same caveats.
- As you might have guessed, you can automatically insert *anything* using this module, as long as you don't mind it inserting just before the closing </head> tag or the closing </body> tag. Copyright statements, survey scripts, "Ted wuz here" alerts for every page...if you think of it, you can do it!
- Again, the fancy GUI stuff doesn't help you in classic pipeline scenarios (other than an XML-encoding aid as described above).
- Typically you want to register scripts as close to the end of your page as possible (various technical performance and usability reasons). However, Google Analytics' latest scripts have a "push" functionality making this a moot point: so register the latest scripts right before the closing </head> tag. See the "Asynchronous Tracking Usage Guide" for more information.
Different web analytics packages have different strengths and weaknesses, and it's only with multiple different perspectives on your site traffic that you even begin to get a clear picture of what is really happening with your site. Using this web analytics module makes it even easier to add and maintain a page tagging solution on your site.
I'd like to just directly link to my compiled DLL and schema file of the module, but unfortunately, it's not at all clear what licensing model is associated with the original module (although it's clear from his article explaining the module, that Microsoft's Ruslan Yakushev intends for us to use it). Therefore, I'll be requesting clarification on this issue, but in the meantime, just download the source code from the original article and make the quick modifications as described above. If you have problems doing so, or you want help deploying it for your site, drop us a line.