ASP.NET integration module
The instructions on this page are intended for self service and online accounts.
Enterprise customers should contact their account managers for integration support.
ClickTale users can download and begin using this Integration module on ASP.NET 1.1 - 4.0 websites and applications to simplify ClickTale procedures. The integration module allows for the automatic injection of ClickTale Script on to all outgoing pages and the automatic caching of page content. You'll be able to use ClickTale for recording pages that were previously problematic, including password protected pages, pages that depend on session objects, pages with random elements and POST processing pages. Its features include:
- Automatic injection of ClickTale script to all outgoing pages.
- Automatic caching of page content.
The benefits of using this module are:
- Having a single location for your ClickTale script makes it easier for you to take advantage of the benefits that ClickTale provides.
- ClickTale will be able to record all sorts of problematic pages such as: password protected pages, pages that depend on session objects, pages with random elements and POST processing pages.
With this release we are targeting web developers and development departments of online companies. Use of this module requires some technical knowledge. This module isn't appropriate to you if you have a PHP or a classic ASP site or if you would like to inject the script into static HTML files.
Installation Guide
ClickTale ASP.NET Integration Module v1.6
The module should work on .NET 1.1 - 4.0 sites.
If you are unable to install a binary module on your site, use the ASP.NET integration code instead.
Step 1 - Getting the archive
Download and unzip the module here.
Create a "bin" folder if not already present in your website and put ClickTaleIntegrationModule.dll inside of it. A .NET 1.1 version of the module can be found in the FX1_1 directory.
Step 2 - Preparing the tracking code for injection
2.1 Remove the existing ClickTale code and/or disable other integration methods
2.2 Locate the ClickTaleScripts.xml file that comes in the ZIP file and open it in a text editor. Paste your ClickTale scripts (which were generated for you by the tracking code generator) into the appropriate CDATA fields in the XML file.
2.3 In the bottom script before the call to ClickTale(###) function add the following line:
ClickTaleFetchFrom="http://%RootPath%/ClickTaleCache.ashx?t=%CacheToken%";
Please note: you do not need to change "%RootPath%/" to a specific Path. It will be replaced automatically during the rendering process, with a value dependent on the page being recorded.
2.4 Check your ClickTaleScripts.xml file - it should now look like this (for the regular, http only, version of the tracking code):
<?xml version="1.0" encoding="utf-8" ?> <scripts> <script name="Top" DoNotReplaceCondition = "<!-- No ClickTale -->|<!-- ClickTale Top part -->"> <![CDATA[<script type="text/javascript"> var WRInitTime=(new Date()).getTime(); </script>]]> </script> <script name="Bottom" DoNotReplaceCondition = "<!-- No ClickTale -->|<!-- ClickTale Bottom part -->"> <![CDATA[<!-- ClickTale Bottom part --> <div id="ClickTale" style="display: none;"></div> <script type="text/javascript"> if(document.location.protocol!='https:') document.write(unescape("%3Cscript src='http://s.clicktale.net/WRb6.js' type='text/javascript'%3E%3C/script%3E")); </script> <script type="text/javascript"> ClickTaleFetchFrom="http://%RootPath%/ClickTaleCache.ashx?t=%CacheToken%"; if(typeof ClickTale=='function') ClickTale([!Your Parameters!]); </script> <!-- ClickTale end of Bottom part -->]]> </script> </scripts>
Save ClickTaleScripts.xml in the root of your web site. You may put it in another place, but then you will have to modify the path of the ScriptsFile parameter on the web.config file.
IMPORTANT NOTE! This code sample relates to http tracking code only! For tracking code which can record both http and https pages you should first make sure your plan offers the ability to record https pages (check if the option is available in the tracking code generation page), then generate SSL/https compliant code and use it in step 2 instead , see below for an example of how the ClickTaleScripts.xml file would look like for the SSL/https compliant code.
<?xml version="1.0" encoding="utf-8" ?> <scripts> <script name="Top" DoNotReplaceCondition = "(<!-- ClickTale Top part -->)"> <![CDATA[<script type="text/javascript"> var WRInitTime=(new Date()).getTime(); </script>]]> </script> <script name="Bottom" DoNotReplaceCondition = "(<!-- ClickTale Bottom part -->)"> <![CDATA[<!-- ClickTale Bottom part --> <div id="ClickTaleDiv" style="display: none;"></div> <script type='text/javascript'> document.write(unescape("%3Cscript%20src='"+ (document.location.protocol=='https:'? 'https://clicktale.pantherssl.com/': 'http://s.clicktale.net/')+ "WRb6.js'%20type='text/javascript'%3E%3C/script%3E")); </script> <script type='text/javascript'> ClickTaleFetchFrom="http://%RootPath%/ClickTaleCache.ashx?t=%CacheToken%"; var ClickTaleSSL=1; if(typeof ClickTale=='function') ClickTale([!YOUR PARAMETERS!]); </script> <!-- ClickTale end of Bottom part -->]]> </script> </scripts>
Step 3 - Configuring the module
Open your website's "web.config" file. Copy the following code right after the <configuration> tag.
Notice that the ClickTale script will be added to all pages that are being served by this specific config file unless a "do not insert" condition is met. See the Q&A section if you need to exclude certain .aspx files from processing.
<configSections> <section name="ClickTale.IntegrationModuleSettings" type="System.Configuration.SingleTagSectionHandler"/> </configSections> <ClickTale.IntegrationModuleSettings ScriptsFile="~\ClickTaleScripts.xml" DoNotProcessCookieName="WRUID" DoNotProcessCookieValue ="0" MaxCachedPages="100" AllowedAddresses ="75.125.82.64/26 50.97.162.64/26"/> <!-- note, this stands for 75.125.82.64 - 75.125.82.127 and 50.97.162.64 - 50.97.162.127 -->
The MaxCachedPages parameter depends on your server hardware capabilities and the amount of maximal memory you want to allocate for caching. Change it according to your needs. Considering that an average page size of about 40KB, 100 cached pages can mean 4Mb of your servers' memory.
Step 4 - Enabling the module
Look for <system.web> element in the config file and insert the following code between the tags:
<httpModules> <add name="ClickTaleIntegrationModule" type="ClickTale.IntegrationModule.ClickTaleIntegrationModule, ClickTaleIntegrationModule" /> </httpModules>
Note: if you already have a <httpModules> section then just copy&paste the <add ...> tag into it.
This activates the module. If you ever want to disable to module it is enough to comment out this section.
Please Note: If you already have tracking code which you entered manually in your pages, you should remove it as it inhibits the module from injecting the tracking code found within the xml file on these pages.
Step 5 - Testing
For optimization purposes, the module will only inject the code for visitors who are classified as "to-record" (have WRUID cookie with non-zero value) or for those who are not classified (no WRUID cookie). Visitors who are classified as "not-to-record" will get no tracking code added to their HTML. As a result you might not see the tracking code in the source of the page. This doesn't mean that the module doesn't work. Your classification depends on your ClickTale recording ratio and luck.
You can use a cookie editor to set the WRUID cookie to some value such as "1".
Alternatively, you can clear cookies, then force yourself to be recorded by following the instructions here note: the advanced selective recording script can be used in the ClickTaleScripts.xml to conditionally record visitors.
Once you are classified as "to-record" you should see the tracking code in the source code of each page on your site and recording should take place. If you still don't see the code, please proceed to the next section.
Troubleshooting and debugging
The module has several debugging facilities. There is a debug page, a log and some configuration flags that control debug levels.
The relevant configuration parameters (for step 3) are:
- AllowDebug - enables access to the debug page which is located at ~/ClickTaleDebug.ashx. Set to "true" to enable this functionality.
- LogFileNameMask - holds the path to the location where the log files are created. Normally in the form LogFileNameMask="~\ClickTaleLog{0}.txt" (where {0} is the current date). The log file has to be enabled for writing by IIS/ASP.
- DebugCode - enables some extra logging of each read and write events in the module. Used to debug difficult cases. The log must also be enabled for this to work correctly. Set to "true" to enable this functionality.
If you don't see the tracking code in your pages, please enable the debug page and try to access it. If you are getting broken recordings, please see the next section for possible causes.
Load Balancing Scenario
The module uses local storage for storing the temporary cache of pageviews content. That content is later requested by ClickTale servers via HTTP(S). When using more than one server and using a load balancer to distribute the requests across the servers there is a chance that a visitor will be forwarded to a different server than the one to which the ClickTale crawler will be forwarded to. As a result the crawler will hit a server that doesn't contain the requested information and the recording (not the response to the visitor) will fail with a 404 error. A proper load balancing configuration should implement one of the following
- A way to force the request form ClickTale to reach a specific server in the farm
- A cache store that is centralized
Forcing a specific server
Using direct host for fetching
If you have a dedicated host for each server in the farm, and you can access resources of the web site by going to a direct url, then you can set ClickTale to fetch from a specific server. To do that you would customize the ClickTaleFetchFrom url of each server to specify a direct url to that server. For example if having a site http://www.site.com/ and servers http://s1.site.com/, http://s2.site.com/ then you would change the bottom tracking code on each server to have ClickTaleFetchFrom url refer to the specific server directlylike this: For the first server:
ClickTaleFetchFrom="http://s1.site.com/ClickTaleCache.ashx?t=%CacheToken%";
For the second server:
ClickTaleFetchFrom="http://s2.site.com/ClickTaleCache.ashx?t=%CacheToken%";
and so on.
Using cookies for accessing a specific server
Some load balancers use a HTTP cookie to assign a specific visitor to a specific server permanently. This is often called "Sticky sessions". If you know that such cookie exists in your case, you should be able to cause the crawler to reach the original server if you record the cookie value. This is done using the FetchFromWithCookies API. To do so, change the ClickTaleFetchFrom line to:
ClickTaleFetchFromWithCookies.setFromCookie("[!COOKIENAME!]"); ClickTaleFetchFrom=ClickTaleFetchFromWithCookies.constructFetchFromUrl("http://%RootPath%/ClickTaleCache.ashx?t=%CacheToken%");
Where [!COOKIENAME!] is the name of the cookie that maintains the visitor's affinity to a specific server.
Centralized cache store - Caching Content To a Database
By default, the cached pages are stored in the application's cache object in server's memory. However, in some cases local cache may not be suitable (e.g. load balancing scenario). For such cases the module has a feature that enables storing cached pages in a database. Please follow these steps if you need to turn this feature on:
- Run a script named "ASP.NET Integration Module SQL Script.sql". This will create the database, table and stored procedures needed. This script can be found in the downloaded zip.
- Add a new connection string that will connect to the new "ClickTale" database, name it "ClickTale".
- Add ConnectionStringName="ClickTale" and MaxCachedSeconds="240" attributes to the ClickTale.IntegrationModuleSettings element in the web.config file. You may also remove MaxCachedPages, because the database mode uses MaxCachedSeconds for cleaning instead.
MaxCachedSeconds represents the number of seconds a cached page will be stored in the database. Entries older than MaxCachedSeconds will be deleted when new entries are inserted. An example of a connection string and a configuration element:
<connectionStrings> <add name="ClickTale" connectionString="Data Source = .\SQLEXPRESS; Initial Catalog = ClickTale; User Id = User; Password = Pass; MultipleActiveResultSets = True" providerName="System.Data.SqlClient" /> </connectionStrings> <ClickTale.IntegrationModuleSettings ScriptsFile="~\ClickTaleScripts.xml" MaxCachedSeconds="60" LogFileNameMask="~\ClickTaleIntegrationModule_{0}_log.txt" AllowedAddresses="75.125.82.64/26 50.97.162.64/26" ConnectionStringName="ClickTale" DoNotProcessCookieName="WRUID" DoNotProcessCookieValue="0" />
Use With "Expires" Header And Enable Reuse Of Cached Pages (if you are getting 404 errors for some of the pages of some of the visitors)
Some websites use "cache-control" and "expires" headers to cache pages on the client. This improves performance but may be problematic when used with our module.
Pages are removed from the module's cache right after they are being accessed (for security and performance reasons). So, if a visitor browses a page more than once without refreshing the content from the server (usually a result of using the back button), ClickTaleCache.ashx will be called several times with the same token. This will cause a cache miss for any request beyond the first one.
To overcome this problem, it is possible to use the DeleteAfterPull="false" parameter in the configuration. This will disable the removal of cached pages when ClickTaleCache.ashx is called. Cached data will be removed after MaxCachedPages="???" new pages are cached, so you might want to extend this parameter as well to allow sufficient traffic between the first pageview and the next (duplicate pageview).
Additionally, you can change your HTTP cache control to "no-cache" which might be more correct for your application logic in the first place.
Please note that "DeleteAfterPull" is not available when caching content to database storage. To achieve the same effect with a "database cache", please edit the "CachePullCachedPage" SP of the ClickTale cache database and change it to only perform: "SELECT Page FROM CachedPages WHERE Token = @Token" . Use "MaxCachedSeconds" parameter instead of "MaxCachedPages" to control the period of time for which to keep the content in cache.
IIS 7 Compatibility
Sometimes there is another step that IIS7 users should perform. If ClickTale Integration Module does not work, please add the following line to your "web.config" file:
<add name="ClickTaleIntegrationModule" type="ClickTale.IntegrationModule.ClickTaleIntegrationModule" preCondition="managedHandler" />
This line should go inside
<system.webServer> <validation validateIntegratedModeConfiguration="false" /> <modules> <!-- Goes Here --> </modules> </system.webServer>
Using with a (reverse) proxy server
If you are using a (reverse) proxy server, that server could change the request in such a way that they seem to appear to originate from the proxy and not from ClickTale servers. This will prevent the module from authenticating the request based on IP address. There are two ways to work around this.
- Change the allowed addresses (“AllowedAddresses”) value in the configuration section of ASP.NET module in your web.config file and set it to the IP of the proxy. Then you need to configure your proxy to block access to ClickTaleCache.ashx file and only grant access from IPs "75.125.82.64/26 50.97.162.64/26" (note, this stands for 75.125.82.64 - 75.125.82.127 and 50.97.162.64 - 50.97.162.127 using CIDR notation).
- or
- If your proxy includes the original IP address in the HTTP headers, then you can add a module setting in your web.config file to instruct the module to use that header. If your proxy uses a header field called "X-Forwarded-For" (this is common), then add IPAddressHeaderFieldName="X-Forwarded-For" to your web.config file to utilize this field.
Conflicts with other modules
In some cases, conflicts can occur with other modules that you may have on your site. This is usually an issue to consider if you are using compression modules rather than IIS built in compression. The conflicts can often be solved by making sure that the ClickTale module is installed on top of the filter chain, such that it can handle the content first. To achieve that try: a) to add the ClickTale Integration Module httpmodule entry as last in the list of modules. b) if 'a' doesn't resolve the issue, try FilterInstallEvent="PostReleaseRequestState" as one of the configuration attributes of the module.
In some cases a CMS will prevent access to our "virtual urls" ClickTaleDebug.ashx or ClickTaleCache.ashx. For example, it might redirect them to a custom not-found page. If you suspect that this is the case, please contact support and request help with setting up "stand alone ASP.NET IM handlers".
If you try browsing to ClickTaleCache.ashx and get a CMS-generated error page, try creating a ClickTaleCache.ashx file (in the root) via Visual Studio and then paste in to the ProcessRequest method the following code:
ClickTale.IntegrationModule.ClickTaleIntegrationModule ct = new ClickTale.IntegrationModule.ClickTaleIntegrationModule(); ct.HandleClickTaleCacheRequest(context.ApplicationInstance);
This should manually run the handler without relying on the httpModule which may not be working because of the CMS. This works for Sitecore CMS.
Multiple domains (inc. TLD)
When migrating from Staging into Production the RootPath can bind to the first request loaded into the app cache (i.e. the first host requested) eg. there can be over a dozen TLDs (hosts) utilising the same app pool in larger sites:
In such cases the line:
ClickTaleFetchFrom="http://%RootPath%/ClickTaleCache.ashx?t=%CacheToken%";can be edited to read:
ClickTaleFetchFrom="http://"+ document.domain +"/ClickTaleCache.ashx?t=%CacheToken%";This should prevent the ClickTale bot querying the same domain for all cached items
Q&A
I have already defined caching correctly on my server. I don't want to change the caching of my pages. Why do you add caching?
The module caches the content of the pages for its own use. This cache has no effect on the delivery of the pages to the visitors, not does it change your existing server side or client side cache scheme. This is a separate cache designed to hold the content temporary in memory until our servers request it from the module.
"Parser Error Message: Exception creating section handler" configuration error is displayed when trying to view pages on the website.
Open your web.config file and change this:
<configSections> <section name="ClickTale.IntegrationModuleSettings" type="System.Configuration.SingleTagSectionHandler" /> </configSections>
- to this:
<configSections> <section name="ClickTale.IntegrationModuleSettings" type="System.Configuration.SingleTagSectionHandler, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> </configSections>
Are cached pages protected from access by third parties?
Yes, several layers of protection are in place. Only certain IPs are allowed to request the cached pages (IPs of ClickTale servers) and only processes which already have access to the page have the secret token required to request the cached content.
Is it possible to inject the script in other places rather than after/before body tags?
Yes. By default the top script is injected after <body> and the bottom before </body>, but this can be changed by adding a InsertAfter attribute to the script[name="Top"] element or adding a InsertBefore attribute to the script[name="Bottom"] element, both are regular expressions.
There is a specific page that I don't want recorded, but the module adds ClickTale script to every page.
The ASP.NET Integration module is a site wide module that will process all pageviews on your site and try to inject the configured ClickTale code into them. You will have to use one of the following solutions to ignore one or more pages (Please note that the first metho is dependent on the content of the page while the second method is dependent on the url of the page):
- You can configure the module to ignore some pages by using the DoNotReplaceCondition attribute on a script element in ClickTaleScripts.xml file. This property is a regular expression, when there is a match for this expression with page content on the page near the InsertBefore/InsertAfter condition, the script will not be added. Make sure that all pages you want to exclude match this condition. For example you can add a note in a HTML comment before the </body> tag that will function as a "do not replace" condition.
- What you will do is:
- 1. Modify your ClickTaleScripts.xml file to have the "DoNotReplaceCondition" property like this:
<script name="Bottom" DoNotReplaceCondition="<!-- No ClickTale -->"> <![CDATA[
- 2. Modify the pages you want to exclude to have the condition right before the </body> tag like this:
<!-- No ClickTale --> </body> </html>
- When the module will detect this text it will not inject the ClickTale code.
- You can also use this mechanism for other strings and conditions you might find in your code. For example, if you only want to include the Clicktale code in pages containing a word or string you can use the code below. For instance it is possible to only record users that are logged in by using a word like: "logout".
DoNotReplaceCondition="^(?![\s\S]*word)"
- The latest versions of the module allow you to define WhitelistURLRegex and BlacklistURLRegex regular expression values in the configuration section. The regular expressions will be matched against the full url of the page. If a white-list is present, then the tracking code will be injected only into urls that match the white-list expression. If a black-list is present, then the tracking code will be injected only into urls that don't match the black-list expression.
Let's say you want to whitelist two pages: page1.aspx and page2.aspx So you would need to put into the the module's configuration section in the web.config the following:
WhitelistURLRegex="(page1\.aspx|page2\.aspx)"To disable code injection for an admin part of the site/CMS the following example can be used.
BlacklistURLRegex="(admin)"- Another option, which is less recommended for ASP.NET, is to use the PHP control script. The PHP control script allows you to set a list of pages to record or ignore and will require you to customize your ClickTale tracking code a little.
Some of my pages already have the ClickTale script; I do not want the script to appear twice.
You should either remove the script from those pages and let the module handle the insertion or you should use DoNotReplaceCondition. See the code step 2 for an example. The default script in Step 2 is already configured to prevent double inclusion.
After installing the module, I tried to watch a recording but I got the following notice instead: "Request from an unauthorized IP." What should I do?
This could be due to a misconfiguration, a proxy, a change in our IP addresses or a hacking attempt. Please check your settings, specifically "AllowedAddresses".
I have installed the module but I don't see the tracking code in the source of the page. What is wrong?
The module will only inject the code for visitors who are selected to be recorded (have the WRUID cookie with a value different from 0 ) or for those who are not classified (i.e. the visitors who do not yet have the WRUID cookie - meaning it has not been decided yet whether they would be recorded). Visitors who are classified as "not-to-be-recorded" will not be presented with the tracking code.
How can I disable the caching and leave only the script injection?
Do note that disabling caching defeats the main purpose of the module and correct page content might not be recorded. The best practice for this case is to put the static tracking code in the website's template. If you still want to use the module for tracking code injection but not for content caching you can add DisableCache="True" to the ClickTale.IntegrationModuleSettings element in the web.config file. When setting DisableCache to True, you need to remove the ClickTaleFetchFrom line from the ClickTaleScripts.xml file or else nothing will be cached.
I'm receiving "The resource cannot be found. Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed..." on my site root page once the module is installed. Full URLs that include the file name produce correct behavior.
Please make sure that you are not using IIS6 with “Wildcard App Mappings” option enable in the IIS config of your site. Such a configuration is not supported by this module.
I'm receiving "Post cache substitution is not compatible with modules in the IIS integrated pipeline that modify the response buffers. Either a native module in the pipeline has modified an HTTP_DATA_CHUNK structure associated with a managed post cache substitution callback, or a managed filter has modified the response." on my site root page once the module is installed.
This happens because you are using post-cache substitution along with ClickTale integration module which is a response filter and they are not compatible.
For more information please read http://support.microsoft.com/kb/2014472.
ClickTale Integration module and post-cache substitution cannot work together.
How is RootPath determined and how do I change it?
The host (which is used for RootPath) is registered once when the module is first loaded. It changes when you restart the web server or when you make a change in the ClickTaleScripts.xml file. To change it back to the value you wanted please restart your web server, then access your site from a URL using the host you wish to serve as root path.