我正在网站上实施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 -->
答案 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表单页面,您可以对母版页执行相同的操作。