IIS中加入piwik跟踪代码
好久没来写博了...
今天写一下如何在IIS中加入piwik跟踪代码。
背景:
• piwik 开源php站点统计程序 http://piwik.org
• HttpModule: http://www.cnblogs.com/stwyhm/archive/2006/08/09/471729.html
实现思路:通过HttpModule在aspx页面的body前加入统计代码。
代码实现:
1. 新建dll项目
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.IO; namespace PiwikAnalytics { /// 修改于网上流传的Google Analytics (https://www.google.com/analytics/) script public class PiwikAnalyticsModule : IHttpModule { static string GoogleScript = string.Empty; HttpApplication application; public void Dispose() { //context.BeginRequest -= new EventHandler(OnBeginRequest); } public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(OnBeginRequest); application = context; } void OnBeginRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; //web.config中定义的站点字符串,后面会有介绍 string sites = ConfigurationManager.AppSettings["PiwikAnalyticsSites"]; //此处未进行异常处理,大家发布时记得加上哦~ string[] siteArr = sites.Split(';'); string siteid = "5"; foreach (string site in siteArr) { if (application.Request.Url.OriginalString.ToLower().IndexOf(site.Split(',')[0]) > 0) { siteid = site.Split(',')[1]; } } GoogleScript = @" <!-- Piwik --> <script type=""text/javascript""> var pkBaseURL = ((""https:"" == document.location.protocol) ? ""https://yourpiwik.com/piwik/"" : ""http://yourpiwik.com/piwik/""); document.write(unescape(""%3Cscript src='"" + pkBaseURL + ""piwik.js' type='text/javascript'%3E%3C/script%3E"")); </script> <script type=""text/javascript""> //try { var piwikTracker = Piwik.getTracker(pkBaseURL + ""piwik.php"", " + siteid + @"); piwikTracker.trackPageView(); piwikTracker.enableLinkTracking(); //} catch (err) { } </script> <noscript> <p> <img id=""img1"" src=""http://pm.taobao.ali.com/piwik/piwik.php?idsite="+siteid+@""" style=""border: 0"" alt="""" /></p> </noscript> <!-- End Piwik Tag -->"; //这里需要针对ASPX页面进行拦截 string[] temp = application.Request.CurrentExecutionFilePath.Split('.'); if (temp.Length > 0 && temp[temp.Length - 1].ToLower() == "aspx") { application.Response.Filter = new AnalyticsStream(application.Response.Filter); } } class AnalyticsStream : Stream { Stream innerStream; MemoryStream memory = new MemoryStream(); public AnalyticsStream(Stream innerStream) { this.innerStream = innerStream; } public override void Close() { memory.Position = 0; using (StreamWriter writer = new StreamWriter(innerStream)) { using (StreamReader reader = new StreamReader(memory)) { while (!reader.EndOfStream) { // Find </body> if (MatchesOrWrite(reader, writer, '<', null) && MatchesOrWrite(reader, writer, '/', "<") && MatchesOrWrite(reader, writer, 'b', "</") && MatchesOrWrite(reader, writer, 'o', "</b") && MatchesOrWrite(reader, writer, 'd', "</bo") && MatchesOrWrite(reader, writer, 'y', "</bod") && MatchesOrWrite(reader, writer, '>', "</body")) { //string script = String.Format(GoogleScript, accountNumber) + "</body>"; writer.Write(GoogleScript); while (!reader.EndOfStream) writer.Write((char)reader.Read()); } } } } base.Close(); } private bool MatchesOrWrite(StreamReader reader, StreamWriter writer, char target, string buffered) { if (!reader.EndOfStream) { char current = (char)reader.Read(); if (current == target) { return true; } else { writer.Write(buffered); writer.Write(current); } } else { writer.Write(buffered); } return false; } public override bool CanRead { get { return memory.CanRead; } } public override bool CanSeek { get { return memory.CanSeek; } } public override bool CanWrite { get { return memory.CanWrite; } } public override void Flush() { memory.Flush(); } public override long Length { get { return memory.Length; } } public override long Position { get { return memory.Position; } set { memory.Position = value; } } public override int Read(byte[] buffer, int offset, int count) { return memory.Read(buffer, offset, count); } public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); } public override void SetLength(long value) { memory.SetLength(value); } public override void Write(byte[] buffer, int offset, int count) { memory.Write(buffer, offset, count); } } } }
2.
编译得到PiwikAnalytics.dll,注册到GAC中【需要强命名的哦~】,不然要每个子站点都拷贝一份。
如何在visual studio中强命名程序集:(推荐) http://www.cnblogs.com/awpatp/archive/2010/02/07/1665530.html
文章中也提到了如果获取程序集的PublicKeyToken,其实不用那么麻烦,把程序集放到GAC中,有一列会显示PublicKeyToken的~。
• GAC注册:http://www.cnblogs.com/mljmalongjiang/archive/2008/07/31/1257135.html
• 另外有种更简便的方式,直接把dll托到 c:\windows\assembly文件夹中【推荐】
另外一种方式强命名程序集:http://www.cnblogs.com/zhongge/articles/1207183.html
经过上述步骤,我们已经把PiwikAnalytics.dll注册到GAC了,那我们在web.config中做一下配置就要大功告成了!
3. web.config默认路径C:\inetpub\wwwroot,如果没有web.config可直接新建的~
<?xml version="1.0"?> <configuration> <appSettings> <add key="PiwikAnalyticsSites" value="site,4;meeting,6"/> </appSettings> <system.web> <authentication mode="Windows"/> <httpModules> <add name="PiwikAnalytics" type="PiwikAnalytics.PiwikAnalyticsModule"/> </httpModules> <compilation debug="true"> <assemblies> <add assembly="PiwikAnalytics, version=1.0.0.0, Culture=neutral,PublicKeyToken=0c64deee0d840dfb" /> </assemblies> </compilation> </system.web> </configuration>
要记得把从步骤2中得到的PublicKeyToken替换成你自己的哦~
到此时,重启iis,刷新页面。再去piwik中查看,大功告成!
需特别注意的地方:
1. 注册module时,要按照自己的实际情况配置
2. 上述方式不适用于MVC和模板模式开发
3. 每次改写代码的时候都需要重新生成一次DLL,并且重新注册GAC,并且对站点相应应用程序池中的进行回收
More:另外介绍2个pwiki客户端查看软件
• Desktop Web Analytics
• Piwik Connector
Over 收工!