在asp.net的每个页面上注入javascript

时间:2015-10-28 12:28:18

标签: javascript asp.net .net asp.net-mvc iis

我正在网站上实施GTM。网站有400多个页面,必须放置GTM脚本。有没有办法在body标签后面的每个页面上注入GTM脚本?网站使用混合技术,一些页面在ASP.NET 4.0中,一些在MVC 4.0中。以下是要添加的示例脚本:

<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-#####"
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-#####');</script>
<!-- End Google Tag Manager -->

3 个答案:

答案 0 :(得分:3)

根据您在问题中所做的编辑,您需要一个HTTP模块来修改注入脚本所生成的代码。

首先,您需要创建一个派生自Stream的类,它将从Response.Filter中包装原始Stream。

public class GtmStream : Stream
{
    private static string gtmScript = @"<!-- Google Tag Manager -->...";

    private Stream _base;

    public GtmStream(Stream stream)
    {
        _base = stream;
    }

    public override void Flush()
    {
        _base.Flush();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return _base.Read(buffer, offset, count);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        var editedBuffer = GetByteArrayWithGtmScriptInjected(buffer);
        _base.Write(editedBuffer, offset, editedBuffer.Length);
    }

    public byte[] GetByteArrayWithGtmScriptInjected(byte[] buffer)
    {
        var stringValue = System.Text.Encoding.UTF8.GetString(buffer);
        if (!string.IsNullOrWhiteSpace(stringValue))
        {
            var position = stringValue.IndexOf("</body>");
            if (position != -1)
            {
                stringValue = stringValue.Insert(position + 7, gtmScript);    
            }
        }
        return System.Text.Encoding.UTF8.GetBytes(stringValue.ToCharArray());
    }

    public override bool CanRead
    {
        get { throw new NotImplementedException(); }
    }

    public override bool CanSeek
    {
        get { throw new NotImplementedException(); }
    }

    public override bool CanWrite
    {
        get { throw new NotImplementedException(); }
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotImplementedException();
    }

    public override void SetLength(long value)
    {
        throw new NotImplementedException();
    }

    public override long Length
    {
        get { throw new NotImplementedException(); }
    }

    public override long Position
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
}

每次调用Write方法时,Stream都会检查它是否包含标记,如果它存在,它将在它之后注入脚本代码。

然后它将返回新的字节数组并在基本Stream上调用Write方法。

要将其插入您的Web应用程序,您需要创建一个HTTP模块,如下所示:

public class GtmScriptModule : IHttpModule
{
    private GtmStream gtmStream;

    public void Init(HttpApplication context)
    {
        context.BeginRequest += new EventHandler(context_BeginRequest);
    }

    void context_BeginRequest(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;
        gtmStream = new GtmStream(application.Context.Response.Filter);
        application.Context.Response.Filter = gtmStream;
    }

    public void Dispose()
    {
    }
}

这只会将Response.Filter设置为您的自定义流。

最后,您需要在Web应用程序中插入HTTP模块:

<system.web>
    ...
    <httpModules>
      <add name="GtmScriptModule" type="TestMvcApplication.Modules.GtmScriptModule, TestMvcApplication" />
    </httpModules>
  </system.web>

<小时/> 如果你想深入了解理论,这里有一些有用的链接:

答案 1 :(得分:1)

尝试创建一个将在每个请求上运行的HTTP模块,检查请求是否针对某个页面,如果是,请发送回您的javascript块

https://msdn.microsoft.com/en-us/library/vstudio/ms227673(v=vs.100).aspx

答案 2 :(得分:1)

对于MVC页面,您应该将脚本放在Web应用程序的默认布局文件中,然后为_ViewStart.cshtml文件中的每个视图设置布局。

对于您的Web表单页面,您可以对母版页执行相同的操作。