现在的位置: 首页 > 综合 > 正文

IIS中加入piwik跟踪代码

2012年01月01日 ⁄ 综合 ⁄ 共 5095字 ⁄ 字号 评论关闭

好久没来写博了...
今天写一下如何在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 收工!

抱歉!评论已关闭.